【问题标题】:Strange behavior during movement of UIElement. Why?UIElement 移动期间的奇怪行为。为什么?
【发布时间】:2013-03-08 14:17:32
【问题描述】:

我在理解(和修复)我遇到的错误时遇到了一些问题。

我的 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() 方法的代码应该不允许我将任何 Canvas 移动到窗口边界之外(它对左上角的 Canvas 非常有效,但不适用于其他 Canvas),如下所示:

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)。目前正试图了解为什么会发生这种情况。

【问题讨论】:

  • 这些画布包含什么,即MainWindow中使用了什么面板? GridCanvas?
  • 在主窗口中有一个网格,其中包含所有其他画布和空间。我将编辑我的帖子并添加 XAML 代码。
  • 不使用渲染转换,为什么不更新它们的Margin 属性,然后将值限制在范围内?因此,如果您计算出Margin.Left 小于0,则将其限制为0。如果它大于250 - Diameter,则将其夹在250 - Diameter。同样处理它为Top;将RightBottom 的边距保留为0。编辑:固定数学:P
  • 我不知道这将如何影响画布在网格内的进一步定位,因为我需要它们的位置来检测与其他画布的相交并计算相交区域。不过,我会试试这个建议,看看它是否有效。我不明白为什么 1 个画布可以完美工作,而另外 2 个根本无法工作。

标签: c# .net wpf uielement wpf-positioning


【解决方案1】:

更新 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相对 点返回到每个包含网格单元。我不确定这个假设是否正确;一个(或两个)比较对于应用程序或类似的东西可能是绝对的。仅通过粗略检查您的代码很难准确确定;您需要运行调试器并检查您的值并查看它们与您期望的不同之处。

【讨论】:

  • 这不仅适用于圆圈,也适用于整个画布。我现在已经尝试了你的建议,但它并没有按预期工作。至于运行调试器,这些是发生的确切步骤:我单击右上角的画布并尝试将其拖到窗口中间。一切顺利。它输入顶部 y 轴约束的 IF。在此之后它退出 ConstrainToBounds() 函数。它转到实际完成动作的地方,但由于尊重是错误的,所以它没有执行。完成 MouseMove 功能后,DraggedElement 消失。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-05
  • 2014-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多