【问题标题】:How to update multiple WPF UserControls asynchronously when an event occurs?事件发生时如何异步更新多个 WPF 用户控件?
【发布时间】:2017-09-21 05:09:20
【问题描述】:

我有一个从本机代码调用的事件处理程序。我需要在那里做一些事情,然后为 4 个不同的 UserControls 调用异步更新。这个想法是事件处理程序可以继续进行,以便可以完成本机端的其他事情。我的第一次尝试是这样的:

interface ISelectedObjectDependent
{
    void SelectedObjectsChanged();
}

public void ObjectSelectionChanged(object sender, EventArgs e)
{
    // this is important stuff that UserControl update methods 
    // need to access
    _selectedObjectIds.Clear();
    _updateIds = true;
    Count = Interface.UI.SelectedObjects.Count;
    ObjectProperties.Instance.AttributeObject = Count == 1
            ? Interface.UI.SelectedObjects.Get().FirstOrDefault()
            : null;

    foreach (var vm in MyApp.ViewModels)
    {
        if (vm.Value is ISelectedObjectDependent)
        {
            App.Current.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action)(() =>
            {
                ((ISelectedObjectDependent) vm.Value).SelectedObjectsChanged();
            }));
        }
    }
 }

实现 ISelectedObjectDependent 的 ViewModel 的方法实现如下:

    public void SelectedObjectsChanged()
    {
        // do some stuff
        // ....
        // refresh datagrid
        ContractsItemsSource.Refresh();
    }

我的问题是:有没有更好的方法来刷新 4 UserControl 内容:

  1. 总执行时间
  2. UI 无响应的总时间
  3. 最长的单次无响应 UI 周期

【问题讨论】:

  • 我不明白你的问题。在 Refresh() 方法执行期间,UI 永远不会响应。
  • 是的,你是对的。我编辑问题。由于测试代码增加了测试速度,我经历了更多的反应迟钝。这按预期工作。我想问题是:“有没有更好的方法来做到这一点?”
  • 一个更好的方法来做什么?
  • 更新了我的问题
  • 为什么需要调用 Refresh?

标签: wpf asynchronous async-await


【解决方案1】:

我的解决方案仅用于限制最长的单次无响应时间和总无响应时间。问题是多个异步调用被分派和执行。

我启动异步方法完全相同,但我通过跟踪调用来限制异步调用的数量。此外,如果没有必要,我根本不打电话,而且我有电话的顺序/优先权。

ISelectedObjectDependent.cs

interface ISelectedObjectDependent
{
    void SelectedObjectsChanged();
    int ExecutionOrder { get; }
    bool NeedsRefresh();
    int QueueCount { get; set; }
}

SelectedObjects.cs

    private List<ISelectedObjectDependent> _viewModels; 

    public void ObjectSelectionChanged(object sender, EventArgs e)
    {            
        _selectedObjectIds.Clear();
        _updateIds = true;
        Count = Interface.UI.SelectedObjects.Count;
        ObjectProperties.Instance.SetAttributeObjectNoRefresh(Count == 1
            ? Interface.UI.SelectedObjects.Get().FirstOrDefault() : null);

        if (_viewModels == null)
        {
            _viewModels = new List<ISelectedObjectDependent>();

            _viewModels = MyApp.ViewModels.Where(vm => vm.Value is ISelectedObjectDependent).Select(vm => (ISelectedObjectDependent)vm.Value)
                .OrderBy(vm => vm.ExecutionOrder)
                .ToList();
        }
        foreach (var vm in _viewModels)
        {
            if (vm.NeedsRefresh() && vm.QueueCount < 1)
            {
                vm.QueueCount++;
                App.Current.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action) (() =>
                {
                    vm.SelectedObjectsChanged();
                }));
            }
        }
    }

ContractsViewModel.cs(4 个实现之一)

public class ContractsViewModel : ViewModel, ISelectedObjectDependent
{
    // only Interface members shown here

    public int ExecutionOrder { get { return 4; } }

    public bool NeedsRefresh()
    {
        return _isVisible;
    }
    public int QueueCount { get; set; }

    public void SelectedObjectsChanged()
    {
        ContractsItemsSource.Refresh();
        RaisePropertyChanged("ContractCount");
        RaisePropertyChanged("InfoText");
        QueueCount--;
    }
}

【讨论】:

    猜你喜欢
    • 2019-02-27
    • 1970-01-01
    • 2011-03-26
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    相关资源
    最近更新 更多