画布中的元素位置未更新

时间:2018-07-30 15:56:25

标签: c# wpf canvas

我在弄清楚如何获取元素相对于画布的更新位置时遇到麻烦。

在我的代码示例中,我将标签添加到画布中的位置(100,100),然后打印标签相对于画布的位置。我还有一个按钮,单击该按钮即可打印位置。

运行代码时,它显示的是(0,0)而不是(100,100)。但是当我单击该按钮时,它会打印(100,100)。

在MainWindow构造函数中的代码与单击按钮以更新标签位置时激活的代码之间会发生什么?而当我希望时如何实现呢?

在将标签添加到画布之后,我尝试在标签和画布上直接使用UpdateLayout(),但是都无效。

隐藏代码:

public partial class MainWindow : Window
{
    Label label;

    public MainWindow()
    {
        InitializeComponent();

        label = new Label();
        label.Content = "Boop";
        Canvas.SetLeft(label, 100);
        Canvas.SetTop(label, 100);

        canvas.Children.Add(label);
        Point p = label.TranslatePoint(new Point(0, 0), canvas);

        Console.WriteLine(p);
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Point p = label.TranslatePoint(new Point(0, 0), canvas);
        Console.WriteLine(p);
    }
}

xaml:

<Window x:Class="CanvasTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CanvasTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Canvas x:Name="canvas" Margin="0">
        <Button Content="Button" Canvas.Left="0" Canvas.Top="0" Width="50" Click="Button_Click"/>
    </Canvas>
</Window>

更新:

在构造函数外部,即在按钮单击逻辑内,具有相同代码的问题相同。如果我尝试在画布上添加一些内容,然后尝试立即获得位置,那么我得到的是0,0,而不是我设置的位置。

新的隐藏代码:

public partial class MainWindow : Window
{
    Label label;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void PrintLabelLocation()
    {
        Point p = label.TranslatePoint(new Point(0, 0), canvas);
        Console.WriteLine(p);
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        label = new Label();
        label.Content = "Boop";

        Canvas.SetLeft(label, 100);
        Canvas.SetTop(label, 100);
        canvas.Children.Add(label);

        PrintLabelLocation();
    }
}

更新2: 添加异步延迟以允许UI呈现时间可以解决该问题。

隐藏代码:

公共局部类MainWindow:Window     {         标签标签;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void PrintLabelLocation()
    {
        Point p = label.TranslatePoint(new Point(0, 0), canvas);
        Console.WriteLine(p);
    }

    private async void Wait(int ms)
    {
        await Task.Delay(ms);
        PrintLabelLocation();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        label = new Label();
        label.Content = "Boop";

        Canvas.SetLeft(label, 100);
        Canvas.SetTop(label, 100);
        canvas.Children.Add(label);

        Wait(1);
    }
}

1 个答案:

答案 0 :(得分:2)

内容尚未呈现,这就是为什么一开始它不显示您设置的位置的原因。看看我在您的背后代码中所做的更改:

public partial class MainWindow : Window
{
    Label label;

    public MainWindow()
    {
        InitializeComponent();

        label = new Label();
        label.Content = "Boop";
        Canvas.SetLeft(label, 100);
        Canvas.SetTop(label, 100);

        canvas.Children.Add(label);

        // Render event - when the controls are at the set location.
        ContentRendered += MainWindow_ContentRendered;
    }

    private void MainWindow_ContentRendered(object sender, EventArgs e)
    {
        PrintLabeLocation();
    }

    // This method allows reuse of code.
    private void PrintLabeLocation()
    {
        Point p = label.TranslatePoint(new Point(0, 0), canvas);
        Console.WriteLine(p);
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        PrintLabeLocation();
    }
}

这将使您了解更多情况。呈现控件后,它们将显示为您设置的位置,发生在构造函数结束且Window可见之后。