WPF ActualWidth为零

时间:2010-12-21 10:40:54

标签: c# .net wpf layout actualwidth

我有一个用户控件,其高度为100,宽度为1920的Canvas

在加载控件时,我转到外部源,下载文本文件并将TextBlock添加到Canvas。然后我想创建一个选框滚动效果应该可以正常工作,除非我将TextBlock添加到Canvas后,我需要得到它们的宽度用于计算但ActualWidth财产总是零。

以下是一些代码:

private readonly LinkedList<TextBlock> textBlocks = new LinkedList<TextBlock>();

public LocalNewsControl()
{
    Loaded += LocalNewsControlLoaded;
}

private void LocalNewsControlLoaded(object sender, RoutedEventArgs e)
{
    LoadDataContext();
}

private void LoadDataContext()
{
    DataContext = new NewsItemsViewModel((exception) => LoadNewsItems());
}

private void LoadNewsItems()
{
    var viewModel = (NewsItemsViewModel)DataContext;

    NewsCanvas.Children.Clear();
    textBlocks.Clear();

    foreach (var newsViewModel in viewModel.NewsItems)
    {
        var tb = new TextBlock
        {
            Text = newsViewModel.Headline,
            FontSize = 28,
            FontWeight = FontWeights.Normal,
            Foreground = Brushes.Black
        };

        NewsCanvas.Children.Add(tb);

        Canvas.SetTop(tb, 20);
        Canvas.SetLeft(tb, -999);

        textBlocks.AddLast(tb);
    }

    Dispatcher.BeginInvoke(new Action(() =>
    {
        var node = textBlocks.First;

        while (node != null)
        {
            if (node.Previous != null)
            {
                //THIS IS WHERE ActualWidth is always ZERO
                var left = Canvas.GetLeft(node.Previous.Value) + node.Previous.Value.ActualWidth + Gap;
                Canvas.SetLeft(node.Value, left);
            }
            else
                Canvas.SetLeft(node.Value, NewsCanvas.Width + Gap);

            node = node.Next;
        }
    }));
}

4 个答案:

答案 0 :(得分:5)

您可以随时将代理人附加到PropertyMetatdata/OnValueChanged,当ActualHeight/ActualWidth从0更改为某些内容时,调整您的滚动,ActualWidth/ActualHeight一旦呈现至少一次就会有一个值:< / p>

LocalNewsControl()
{
    var descriptor = DependencyPropertyDescriptor.FromProperty(ActualWidthProperty, typeof(TextBlock));
    if (descriptor != null)
        descriptor.AddValueChanged(myTextBlock, ActualWidth_ValueChanged);
}

private void ActualWidth_ValueChanged(object a_sender, EventArgs a_e)
{
   //Modify you scroll things here
   ...
}

答案 1 :(得分:3)

如果你想坚持你的调度员调用 - 将优先级设置为加载,那么它将与加载的事件同时调用,你应该有一个值。 BeginInvoke上存在一个过载,它也具有优先级。

答案 2 :(得分:1)

任何Control的{​​{1}}或ActualHeightActualWidth&gt;之前始终为零Loaded&gt; Measured&gt; Arranged

在您的情况下,我建议您使用RenderedLoaded的{​​{1}}事件。

答案 3 :(得分:0)

Canvas用于TextBlock的布局是否有任何特殊原因?如果没有,你最好使用水平方向的StackPanel,它将为你处理布局数学。