2013-03-08 48 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