首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WPF ActualWidth为零

WPF ActualWidth为零
EN

Stack Overflow用户
提问于 2010-12-21 18:40:54
回答 4查看 8.3K关注 0票数 6

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

在加载控件时,我转到外部源,下载一个文本文件并将TextBlock添加到画布中。然后,我想创建一个字幕滚动效果,它应该工作得很好,除了在我将TextBlock添加到Canvas之后,我需要获取它们的宽度以便于计算,但ActualWidth属性始终为零。

下面是一些代码:

代码语言:javascript
复制
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;
        }
    }));
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-12-21 19:44:55

如果您想继续使用dispatcher调用-将优先级设置为loaded,那么它将与loaded事件同时被调用,并且您应该有一个值。BeginInvoke上也有一个重载,它也具有优先级。

票数 3
EN

Stack Overflow用户

发布于 2010-12-21 20:04:46

你可以随时在PropertyMetatdata/OnValueChanged上附加一个delgate,当ActualHeight/ActualWidth从0变为某个值时,调整你的滚动,ActualWidth/ActualHeight会有一个值,一旦它渲染了至少一次:

代码语言:javascript
复制
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
   ...
}
票数 5
EN

Stack Overflow用户

发布于 2010-12-21 18:52:34

任何ControlActualHeightActualWidthLoaded > Measured > Arranged > Rendered之前总是为零。

在您的情况下,我建议使用对您有利的TextBlockLoadedSizeChanged事件。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4498397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档