При изменении свойства запускается долгосрочное задание для заполнения другого свойства

1

Хорошо, поэтому я пытаюсь научить себя шаблону 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
    }
}
  • 1
    ObservableCollection требует потока пользовательского интерфейса. Вы можете подготовить List<BindedLimit> в фоновом режиме (используя Thread , Task и т. Д.), А затем вызвать обновление ObservableCollection . Смотрите здесь
  • 0
    Хорошо, я не знал этого о ObservableCollection. Так что, если я реализую команду в той ссылке, которую вы мне прислали, как мне вызвать ее при изменении выбора? Я просто вызываю Command.Execute в сеттере?
Теги:
wpf
mvvm

2 ответа

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));
}
0

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню