【问题标题】:On property change kickoff long running task to populate another property在属性更改启动长时间运行任务以填充另一个属性
【发布时间】:2014-12-12 14:57:42
【问题描述】:

好的,所以我正在尝试自学 MVVM 模式和 WPF,但我遇到了障碍。

我有一个具有“SelectedProduct”字段的 ViewModel。设置 SelectedProduct 字段后,我想通过调用长时间运行的函数来填充另一个属性“BindedLimits”的内容(这大约需要 2-10 秒,具体取决于所选产品)。理想情况下,我想在后台启动更新,并在发生这种情况时以某种方式显示“进度”窗口,但我似乎找不到任何关于如何完成此操作的可靠资源,或者如果这甚至是做这样的事情的“正确”方式。

到目前为止,这是我的 ViewModel...

public class LimitsViewModel : PropertyChangedBase
{

    private ProductFamily selectedProduct;

    public ProductFamily SelectedProduct
    {
        get { return this.selectedProduct; }
        set
        {
            bool runLongOperation = true;

            if (value == this.selectedProduct)
            {
                runLongOperation = false;
            }

            this.SetPropertyChanged(ref this.selectedProduct, value);

            if (runLongOperation)
            {
                this.Limits = LoadLimits();
            }
        }
    }

    private ObservableCollection<BindedLimit> limits;

    public ObservableCollection<BindedLimit> Limits
    {
        get { return this.limits; }
        set
        {
            this.SetPropertyChanged(ref this.limits, value);
        }
    }

    private BindedLimit selectedLimit;

    public BindedLimit SelectedLimit
    {
        get { return this.selectedLimit; }
        set
        {
            this.SetPropertyChanged(ref this.selectedLimit, value);
        }
    }

    private ObservableCollection<BindedLimit> LoadLimits()
    {
        // Long running stuff here
    }
}

【问题讨论】:

  • ObservableCollection 需要 UI 线程。您可以在后台准备List&lt;BindedLimit&gt;(使用ThreadTask 等),然后调用ObservableCollection 的更新。见here
  • 好的,我不知道 ObservableCollection。因此,如果我在您发送给我的那个链接中实现命令,我如何在选择更改时调用它?我只是在 setter 中调用 Command.Execute 吗?

标签: c# wpf mvvm


【解决方案1】:

类似

private ProductFamily _selectedProduct;
public ProductFamily SelectedProduct
{
    get { return _selectedProduct; }
    set
    {
        this.SetPropertyChanged(ref _selectedProduct, value)
        Limits.Clear(); // or Limits = new ...
        Task.Run(() => LongTask());
    }
}

private void LongTask()
{
    var list = new List<BindedLimit>();
    ...
    App.Current.Dispatcher.Invoke(() => Limits = new ObservableCollection<BindedItems>(list));
}

【讨论】:

    【解决方案2】:

    Sinatr 指向What's the best way to update an ObservableCollection from another thread? 的链接帮助我找到了解决方案。这是我设计的。谢谢!

    public class LimitsViewModel : PropertyChangedBase
    {
        private CancellationTokenSource tokenSource;
    
        public LimitsViewModel()
        {
            this.tokenSource = new CancellationTokenSource();
        }
    
        public ICommand LoadCommand
        {
            get { return new RelayCommand(async x => await this.LoadLimits(this.tokenSource.Token)); }
        }
    
        private ProductFamily selectedProduct;
        public ProductFamily SelectedProduct
        {
            get { return this.selectedProduct; }
            set
            {
                this.SetPropertyChanged(ref this.selectedProduct, value);
                this.LoadCommand.Execute(null);
            }
        }
    
        private ObservableCollection<BindedLimit> limits;
        public ObservableCollection<BindedLimit> Limits
        {
            get { return this.limits; }
            set { this.SetPropertyChanged(ref this.limits, value); }
        }
    
        private bool limitsLoading;
        public bool LimitsLoading
        {
            get { return this.limitsLoading; }
            set { this.SetPropertyChanged(ref this.limitsLoading, value); }
        }
    
        private BindedLimit selectedLimit;
        public BindedLimit SelectedLimit
        {
            get { return this.selectedLimit; }
            set { this.SetPropertyChanged(ref this.selectedLimit, value); }
        }
    
        private async Task LoadLimits(CancellationToken ct)
        {
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-10-30
      • 2020-02-21
      • 2022-11-04
      • 2017-04-24
      • 1970-01-01
      • 1970-01-01
      • 2013-06-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多