简体   繁体   中英

TransformToAncestor doesn't always work

I'm currently working on my first WPF app. I'm getting data from some XML file and based on that file I populate stackpanel with some dynamically created buttons.

later on I need to retrieve X coordinate from specific button for which i use method:

private double GetStationCoordinates(int stationIdx)
    {
        foreach (Button station in StationMap.Children)
        {
            if (stationIdx != Convert.ToInt16(station.Tag)) continue;
            var relativePoint = station.TransformToAncestor(Application.Current.MainWindow).Transform(new Point(0, 0));
            //Console.WriteLine(stationIdx + " " + relativePoint.ToString());
            return relativePoint.X;
        }
        return 0;
    }

And then I use this coordinates to paint some points in other panel under the buttons. It all worked fine until I set my main window property

SizeToContent="WidthAndHeight"

Now - when I paint my points for the first time after launching the app (and after I populate StackPanel with buttons) they all (points) receive the same X coordinate - 11. When i hit Refresh button everything is ok.But the first paint - just after adding buttons is problematic. Same problem occurs when I reload buttons configuration xml file. I'm starting with clearing all the Children in StackPanel and populating it with new ones. After that first painting of points is broken - GetStationCoordinates returns 11 for every button. Is it somehow connected to autosize property of main window?

You're probably trying to get the position of elements that haven't been correctly positioned yet. Defer that code until the view has loaded, using any of these two approaches:

a) Subscribe to the Loaded event of the view and do it there.

private void Window_Loaded(object sender, EventArgs e)
{
    this.Loaded -= Window_Loaded;  // Or else it could get called again later

    int id;
    // do stuff

    GetStationCoordinates(id);
}

b) Put it in an asynchronous call with Dispatcher.BeginInvoke

private void SomeCode()
{
    int id;
    // do other stuff

    Dispatcher.BeginInvoke(new Action(() =>
        {
            GetStationCoordinates(id);
        }),
        DispatcherPriority.Loaded);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM