Dispatcher只在它第一次被调用时更新UI

本文关键字:调用 更新 UI 第一次 Dispatcher | 更新日期: 2023-09-27 18:06:41

我有一个类,它执行可能长时间运行的操作,因此它通过触发事件来报告其进度,并且我计划在与UI分开的线程中运行它。为了测试状态消息事件是否会按计划更新绑定列表框,我创建了一个具有相同事件类型的虚拟类:

class NoisyComponent
{
    public EventHandler<string> OnProgress;
    protected void prog(params string[] msg)
    {
        if (OnProgress != null)
            OnProgress(this, string.Join(" ", msg));
    }
    public void Start(int lim)
    {
        for (int i = 0; i < lim; i++)
        {
            prog("blah blah blah", i.ToString());
            System.Threading.Thread.Sleep(200);
        }
    }
}

我正在测试的页面有一个列表框:

    <ListBox ItemsSource="{Binding Path=appstate.progress_messages, Source={x:Static Application.Current}}"></ListBox>

我在OnRender中开始任务:

    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);
        var noisy = new NoisyComponent();
        noisy.OnProgress += (sender, msg) =>
        {
            Dispatcher.Invoke(() =>
            {
                (App.Current as App).appstate.progress_messages.Add(msg);
                UpdateLayout();
            });
        };
        Task.Run(() => { noisy.Start(5); });
    }

appstate.progress_messages是一个依赖属性

    public List<string> progress_messages
    {
        get { return (List<string>)GetValue(progress_messagesProperty); }
        set { SetValue(progress_messagesProperty, value); }
    }
    public static readonly DependencyProperty progress_messagesProperty =
        DependencyProperty.Register("progress_messages", typeof(List<string>), typeof(AppState), new PropertyMetadata(new List<string>()));

我期望在列表框中每隔200毫秒看到一个新的"blah blah blah #"行,但是我只看到了第一行("blah blah blah 0"),没有其他内容。我在Dispatcher.Invoke lambda中设置了一个断点,它肯定会运行多次,并且属性正在更新,但它只是没有显示在UI中。

我认为问题可能是,因为属性是一个列表,它只被分配给一次,然后Add方法正在调用现有对象,并且变化没有被依赖属性"检测"。但是到目前为止,我还没有发现如果依赖项属性是一个集合,那么需要哪些特殊步骤。

我做错了什么?

Dispatcher只在它第一次被调用时更新UI

我不确定,但是…

尝试将progress_messages设置为ObservableCollection

public ObservableCollection<string> progress_messages
    {
        get { return (ObservableCollection<string>)GetValue(progress_messagesProperty); }
        set { SetValue(progress_messagesProperty, value); }
    }
    public static readonly DependencyProperty progress_messagesProperty =
        DependencyProperty.Register("progress_messages", typeof(ObservableCollection<string>), typeof(AppState), new PropertyMetadata(new ObservableCollection<string>()));