在物业变更启动长期运行任务以填充另一个物业

时间:2014-12-12 14:57:43

标签: c# wpf mvvm

好的,所以我试图自学MVVM模式和WPF,并且我遇到了阻塞。

我有一个ViewModel,它有一个" SelectedProduct"领域。当设置了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
    }
}

2 个答案:

答案 0 :(得分: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));
}

答案 1 :(得分:0)

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)
    {
    }
}