2013-03-08 4 views
2

내가 겪고있는 버그를 이해하는 데 어려움이 있습니다. 연한 파랑의 색 그 지역의UIElement의 이동 중에 이상한 동작이 발생합니다. 왜?

모든 캔버스이며, 그들이 이동 가능 :

나는 다음 그림에서와 같은 UI를 가지고있다. 이것은 내가 내 문제가있는 곳이다. 왼쪽 상단의 것이 문제없이 움직일 수 있습니다. 다른 두 사람, 내가 그들을 끌고있을 때, 사라집니다. 나는 이유를 설명 할 수 없다.

요소의 이동에 대한 코드입니다 :

// 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'? –

+0

주 창에는이 모든 다른 캔버스와 공간이있는 표가 있습니다. 내 게시물을 편집하고 XAML 코드도 추가합니다. – Andrei

+1

렌더 변환을 사용하는 대신, 단지'Margin' 속성을 업데이트 한 다음 값을 경계 내에서 클램핑하지 않는 것이 어떻습니까? 따라서 'Margin.Left'가 '0'보다 작지 않은 것으로 계산하면 '0'으로 고정하십시오. '250 - Diameter'보다 크면 '250 - Diameter'로 고정하십시오. 마찬가지로'Top'을 처리합니다. '오른쪽'과 '하단'여백을 0으로 둡니다. 편집 : 고정 수학 : P –

답변

0

대신 변환을 렌더링 사용하는, 캔버스의 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