C# 属性更改时启动长时间运行的任务以填充另一个属性

C# 属性更改时启动长时间运行的任务以填充另一个属性,c#,wpf,mvvm,C#,Wpf,Mvvm,好的,所以我试图自学MVVM模式和WPF,我遇到了一个障碍 我有一个ViewModel,它有一个“SelectedProduct”字段。设置SelectedProduct字段后,我想通过调用长时间运行的函数来填充另一个属性“BindedLimits”的内容(根据所选的产品,大约需要2-10秒)。理想情况下,我希望在后台启动更新,并在更新过程中显示一个“进度”窗口,但我似乎找不到任何可靠的资源来说明如何完成更新,或者这是否是这样做的“正确”方式 这是迄今为止我的ViewModel public c

好的,所以我试图自学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
    }
}
public class LimitsViewModel:PropertyChangedBase
{
私人产品系列精选产品;
公共产品系列精选产品
{
获取{返回this.selectedProduct;}
设置
{
bool runlong操作=真;
如果(值==此.selectedProduct)
{
runLongOperation=false;
}
this.SetPropertyChanged(参考this.selectedProduct,value);
if(长时间运行)
{
this.Limits=LoadLimits();
}
}
}
私人可观测收集限额;
公共可观测收集限值
{
获取{返回this.limits;}
设置
{
this.SetPropertyChanged(参考this.limits,value);
}
}
私有绑定限制selectedLimit;
公共绑定限制SelectedLimit
{
获取{返回this.selectedLimit;}
设置
{
this.SetPropertyChanged(参考this.selectedLimit,value);
}
}
私有ObservableCollection负载限制()
{
//这里有长跑的东西
}
}
类似

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));
}
private ProductFamily\u选择的产品;
公共产品系列精选产品
{
获取{return\u selectedProduct;}
设置
{
此.SetPropertyChanged(参考所选产品,值)
Limits.Clear();//或Limits=new。。。
Task.Run(()=>longstask());
}
}
私人有限公司
{
var list=新列表();
...
App.Current.Dispatcher.Invoke(()=>Limits=newobserveCollection(list));
}
Sinatr的链接帮助我找到了解决方案。这是我设计的。谢谢

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)
    {
    }
}
public class LimitsViewModel:PropertyChangedBase
{
私有取消令牌源令牌源;
public LimitsViewModel()
{
this.tokenSource=新的CancellationTokenSource();
}
公共ICommand LoadCommand
{
获取{return new RelayCommand(async x=>wait this.LoadLimits(this.tokenSource.Token));}
}
私人产品系列精选产品;
公共产品系列精选产品
{
获取{返回this.selectedProduct;}
设置
{
this.SetPropertyChanged(参考this.selectedProduct,value);
this.LoadCommand.Execute(null);
}
}
私人可观测收集限额;
公共可观测收集限值
{
获取{返回this.limits;}
set{this.SetPropertyChanged(ref this.limits,value);}
}
私人布尔有限公司;
公共图书馆有限公司
{
获取{返回this.limitsLoading;}
set{this.SetPropertyChanged(ref this.limitsLoading,value);}
}
私有绑定限制selectedLimit;
公共绑定限制SelectedLimit
{
获取{返回this.selectedLimit;}
set{this.SetPropertyChanged(ref this.selectedLimit,value);}
}
专用异步任务负载限制(CancellationToken ct)
{
}
}

可观察收集
需要UI线程。您可以在后台准备
列表
(使用
线程
任务
等),然后调用
可观察集合的更新
。看,好吧,我不知道可观测的收集。因此,如果我在您发送给我的链接中实现该命令,我如何在选择更改时调用它?我是否只调用Command.Execute在setter中执行?