Хорошо, поэтому я пытаюсь научить себя шаблону 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
}
}
Что-то вроде
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));
}
Sinatr ссылка на Что лучший способ обновить ObservableCollection из другого потока? помогли мне понять решение. Вот что я придумал. Благодарю!
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)
{
}
}
ObservableCollection
требует потока пользовательского интерфейса. Вы можете подготовитьList<BindedLimit>
в фоновом режиме (используяThread
,Task
и т. Д.), А затем вызвать обновлениеObservableCollection
. Смотрите здесь