2013-03-08 77 views
2

我在理解(并修复)我遇到的错误时遇到了一些麻烦。UIElement移动过程中的奇怪行为。为什么?

我有一个像下面的图片中的UI:

在lightblue彩色这些地区的

所有的画布,他们是可移动的。这是我遇到问题的地方。左上角的那个可以毫无问题地移动。另外两个,当我拖着它们时,就消失了。我无法解释为什么。

这是元素的移动代码:

// this is all inside the MouseMove event handler function 

// If there is no dragged element 
if (this.DraggedElement == null || !this.IsDragInProgress) 
    return; 

/* 
* Calculating the new position for the dragged element 
*/ 

// Mouse current position 
Point cursor = e.GetPosition(this); 

double xMove = 0; 
double yMove = 0; 

// Movement detected 
if (cursor != MouseClickLocation) 
{ 
    // Moving on the x-axis and y-axis 
    xMove = cursor.X - MouseClickLocation.X; 
    yMove = cursor.Y - MouseClickLocation.Y; 

    // Actually moving the element 
    if (this.ConstrainToBounds(this.DraggedElement, mainWindow)) 
    { 
     TranslateTransform translate = new TranslateTransform(xMove, yMove); 

     this.DraggedElement.RenderTransform = translate; 
    } 
} 

为ConstrainToBounds()方法的代码应该不会让我移动任何画布的窗口边框外(它完美的左上角帆布,而不是为别人),并如下:

private Boolean ConstrainToBounds(Canvas element, UIElement container) 
{ 
    try 
    { 
     Boolean respects = true; 

     // Values used to reset the element position to a proper location 
     double xReset = 0; 
     double yReset = 0; 

     // Left x-axis constraint 
     if (element.TranslatePoint(new Point(), container).X <= new Point(0, 0).X) 
     { 
      respects = false; 

      // Get elements' current position and adjust 
      xReset = element.TranslatePoint(new Point(), container).X + 1; 
      yReset = element.TranslatePoint(new Point(), container).Y; 

      TranslateTransform translate = new TranslateTransform(xReset, yReset); 

      element.RenderTransform = translate; 
     } 

     // Right x-axis constraint 
     if (element.TranslatePoint(new Point(), container).X + element.RenderSize.Width >= container.RenderSize.Width) 
     { 
      respects = false; 

      // Get elements' current position and adjust 
      xReset = element.TranslatePoint(new Point(), container).X - 1; 
      yReset = element.TranslatePoint(new Point(), container).Y; 

      TranslateTransform translate = new TranslateTransform(xReset, yReset); 

      element.RenderTransform = translate; 
     } 

     // Top y-axis constraint 
     if (element.TranslatePoint(new Point(), container).Y <= new Point(0, 0).Y) 
     { 
      respects = false; 

      // Get elements' current position and adjust 
      xReset = element.TranslatePoint(new Point(), container).X; 
      yReset = element.TranslatePoint(new Point(), container).Y + 1; 

      TranslateTransform translate = new TranslateTransform(xReset, yReset); 

      element.RenderTransform = translate; 
     } 

     // Bottom y-axis constraint 
     if (element.TranslatePoint(new Point(), container).Y + element.RenderSize.Height >= container.RenderSize.Height) 
     { 
      respects = false; 

      // Get elements' current position and adjust 
      xReset = element.TranslatePoint(new Point(), container).X; 
      yReset = element.TranslatePoint(new Point(), container).Y - 1; 

      TranslateTransform translate = new TranslateTransform(xReset, yReset); 

      element.RenderTransform = translate; 
     } 

     return respects; 
    } 
    catch (Exception ex) 
    { 
     throw ex; 
    } 
} 

Edit_1:从MainWindow.xaml增加了代码:

<Window 
Name="mainWindow" 
x:Class="WPF_TestApp.MainWindow" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="MainWindow" Height="480" Width="555"> 

<Grid Name="mainGrid"> 
    <Canvas Grid.Row="0" 
      Grid.Column="0" 
      Background="AliceBlue" 
      Name="LeftTop" 
      MouseDown="onMouseDown" 
      MouseMove="onMouseMove" 
      MouseUp="onMouseUp" > 

     <Ellipse Fill="Blue" 
     Width="100" 
     Height="100"/> 
    </Canvas> 

    <Canvas Grid.Row="0" 
      Grid.Column="2" 
      Background="AliceBlue" 
      Name="RightTop" 
      MouseDown="onMouseDown" 
      MouseMove="onMouseMove" 
      MouseUp="onMouseUp"> 
     <Ellipse Fill="Blue" 
     Width="100" 
     Height="100"/> 
    </Canvas> 

    <Label Grid.Row="2" 
      Grid.Column="0" 
      Name="LeftBottom"> 
    </Label> 

    <Canvas Grid.Row="2" 
      Grid.Column="3" 
      Background="AliceBlue" 
      Name="RightBottom" 
      MouseDown="onMouseDown" 
      MouseMove="onMouseMove" 
      MouseUp="onMouseUp"> 
     <Ellipse Fill="Blue" 
     Width="100" 
     Height="100"/> 
    </Canvas> 

    <Grid.RowDefinitions> 
     <RowDefinition Height="200" /> 
     <RowDefinition Height="50" /> 
     <RowDefinition Height="200" /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="250" /> 
     <ColumnDefinition Width="50" /> 
     <ColumnDefinition Width="250" /> 
    </Grid.ColumnDefinitions> 
</Grid> 
</Window> 

Edit_2:所以,我发现当我移动右上角的画布时,它实际上移动到视图之外(位置600,0)。目前试图了解为什么发生这种情况。

+0

什么是包含这些画布,即什么面板用于'MainWindow'?一个'Grid'或'Canvas'? – 2013-03-08 14:33:35

+0

在主窗口中有一个网格,其中有所有这些其他画布和空格。我将编辑我的文章并添加XAML代码。 – Andrei 2013-03-08 14:35:03

+1

而不是使用渲染变换,为什么不更新他们的'Margin'属性,然后将值限制在边界内?所以如果你计算'Margin.Left'小于'0',将它钳到'0'。如果它大于'250 - Diameter',则将其固定为'250 - Diameter'。同样的处理它的顶部;将Right和Bottom边距设置为0.编辑:固定数学:P – 2013-03-08 14:38:03

回答

0

而不是使用渲染变换,可能会更容易更新Canvas的Margin属性:

if (cursor != MouseClickLocation) 
{ 
    // Moving on the x-axis and y-axis 
    xMove = cursor.X - MouseClickLocation.X; 
    yMove = cursor.Y - MouseClickLocation.Y; 

    // Actually moving the element 
    this.DraggedElement.Margin = this.CalculateNewPosition(this.DraggedElement, mainWindow, xMove, yMove); 
} 

CalculateNewPosition可能是这个样子(警告,未经测试):

private Thickness CalculateNewPosition(Canvas element, UIElement container, double translationX, double translationY) 
{ 
    Thickness currentPosition = element.Margin; 
    Thickness newPosition = new Thickness(currentPosition.Left + translationX, currentPosition.Top + translationY, 0, 0); 

    int containerWidth = container.ActualWidth; 
    int containerHeight = container.ActualHeight; 
    int elementWidth = element.ActualWidth; 
    int elementHeight = element.ActualHeight; 

    if (newPosition.Left < 0) 
     newPosition.Left = 0; 
    else if (newPosition.Left + elementWidth > containerWidth) 
     newPosition.Left = containerWidth - elementWidth; 

    if (newPosition.Top < 0) 
     newPosition.Top = 0; 
    else if (newPosition.Top + elementHeight > containerHeight) 
     newPosition.Top = containerHeight - elementHeight; 

    return newPosition; 
} 

我不确定为什么特别是你的代码不适用于其他圈子。可能它具有与边界检查等做:

if (element.TranslatePoint(new Point(), container).X <= new Point(0, 0).X) 
if (element.TranslatePoint(new Point(), container).X + element.RenderSize.Width >= container.RenderSize.Width) 

的假设是new Point(0,0)TranslatePoint在返回点相对到各含有网格单元。我不确定这个假设是否正确;一个(或两个)比较对于应用程序可能是绝对的,或者对于这个效果有些东西。仅通过粗略检查你的代码就很难确定;你需要运行调试器并检查你的值,看看它们与你期望的不同。

+0

这不仅仅是为了圆圈,它是为了完整的画布。我已经尝试了您的建议,但并不像预期的那样工作。至于运行调试器,这些都是发生的确切步骤:我单击右上角的画布并尝试将它拖到窗口的中间位置。一切安好。它进入顶部y轴约束的IF。之后它退出ConstrainToBounds()函数。它移动到实际完成的位置,但由于尊重是错误的,所以不会执行。并在完成MouseMove函数后,DraggedElement消失。 – Andrei 2013-03-08 15:18:42