Обновите UI от класса ViewModel (шаблон MVVM) в WPF

О, один большой взлом, который я использовал несколько лет назад, то, что Windows не позволит Вам , удаляют файлы, но это действительно позволяет Вам перемещение их.

Pseudo-sort-of-code:

mv %WINDIR%\System32\mfc42.dll %WINDIR\System32\mfc42.dll.old
Install new mfc42.dll
Tell user to save work and restart applications

, Когда перезапущенные приложения (отмечают, что мы не должны были перезагружать машину), они загрузили новое mfc42.dll, и все было хорошо. Это, вместе с PendingFileOperations для удаления старого в следующий раз целая перезапущенная система, работало вполне прилично.

9
задан Oscar Mederos 4 March 2013 в 10:25
поделиться

6 ответов

Вы должны попробовать без флага O_NONBLOCK. в необработанном режиме, если настройки c_cc [VMIN] и c_cc [VTIME] равны 0, последовательный порт ведет себя следующим образом (согласно man cfmakeraw):

Если данные есть в наличии, прочтите возврат немедленно, с меньшим из количество доступных байтов, или количество запрошенных байтов. Если нет данных

В обработчике событий RunWorkerCompleted , который выполняется в потоке пользовательского интерфейса, вы устанавливаете для IsBusySaving значение false и, возможно, изменяете другие элементы пользовательского интерфейса, чтобы показать, что вы закончили.

Пример кода (непроверенный):

BackgroundWorker bwSave;
DependencyProperty IsBusySavingProperty = ...;

private MyViewModel() {
    bwSave = new BackgroundWorker();

    bwSave.DoWork += (sender, args) => {
        // do your lengthy save stuff here -- this happens in a separate thread
    }

    bwSave.RunWorkerCompleted += (sender, args) => {
        IsBusySaving = false;
        if (args.Error != null)  // if an exception occurred during DoWork,
            MessageBox.Show(args.Error.ToString());  // do your error handling here
    }
}

private void Save() {
    if (IsBusySaving) {
        throw new Exception("Save in progress -- this should be prevented by the UI");
    }
    IsBusySaving = true;
    bwSave.RunWorkerAsync();
}
11
ответ дан 4 December 2019 в 14:29
поделиться

Вы всегда можете сделать что-то вроде этого:

public class SaveDemo : INotifyPropertyChanged
{
  public event PropertyChangedEventHandler PropertyChanged;
  private bool _canSave;

  public bool CanSave
  {
    get { return _canSave; }
    set
    {
      if (_canSave != value)
      {
        _canSave = value;
        OnChange("CanSave");
      }
    }
  }

  public void Save()
  {
    _canSave = false;

    // Do the lengthy operation
    _canSave = true;
  }

  private void OnChange(string p)
  {
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
      handler(this, new PropertyChangedEventArgs(p));
    }
  }
}

Затем вы можете привязать свойство IsEnabled кнопки к свойству CanSave, и оно будет автоматически включено / отключено. Альтернативный метод, который я бы выбрал, - это использовать команду CanExecute для сортировки, но идея достаточно похожа, чтобы вы могли с ней работать.

0
ответ дан 4 December 2019 в 14:29
поделиться

Вы используете шаблон MVVM, поэтому для вашей команды кнопки «Сохранить» установлен экземпляр объекта RoutedCommand, который добавляется в коллекцию CommandBindings окна либо декларативно, либо императивно.

Предполагая, что вы сделать это декларативно. Что-то вроде

<Window.CommandBindings>
    <CommandBinding
        Command="{x:Static namespace:ClassName.StaticRoutedCommandObj}"
        CanExecute="Save_CanExecute"
        Executed="Save"
    />
</Window.CommandBindings>

Для обработчика перенаправленного события Executed, вашего метода Save (), при входе вы устанавливаете для переменной значение false, при возврате вы устанавливаете ее обратно в true. Что-то вроде.

void Save(object sender, ExecutedRoutedEventArgs e)
{
    _canExecute = false;
    // do work
    _canExecute = true; 
}

Для обработчика перенаправленного события CanExecute, метода Save_CanExecute (), вы используете переменную как одно из условий.

void ShowSelectedXray_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = _canExecute && _others;
}

Я надеюсь, что все понятно. :)

3
ответ дан 4 December 2019 в 14:29
поделиться

Вы можете сделать это с помощью следующего кода ..

Thread workerThread = null;
void Save(object sender, ExecutedRoutedEventArgs e)
{
workerThread = new Thread(new ThreadStart(doWork));
SaveButton.isEnable = false;
workerThread.start();
}

выполните весь ваш длительный процесс в dowork () метод

каким-нибудь другим методом ...

workerThread.join();
SaveButtton.isEnable = true;

Это приведет к запуску длительного процесса сохранения в другом потоке и не заблокирует ваш пользовательский интерфейс. Если вы хотите показывать анимацию, когда пользователь нажимает кнопку сохранения, а затем показывает индикатор выполнения, например, iPhone и т. Д., Дайте мне обратную связь, я буду постараюсь помочь вам еще больше.

0
ответ дан 4 December 2019 в 14:29
поделиться

Запоздалый ответ, но я подумал, что было бы неплохо внести и свою лепту.

Вместо того, чтобы создавать свой собственный новый поток, вероятно, было бы лучше оставить выполнение сохранения на усмотрение threadpool. Это не заставит его запуститься мгновенно, как создание собственного потока, но позволит вам сэкономить ресурсы потоков.

Сделать это можно следующим образом:

ThreadPool.QueueUserWorkItem(Save);

Проблема с использованием этого подхода заключается в том, что метод "Save()" должен принимать объект, который будет действовать как состояние. У меня была проблема, похожая на вашу, и я решил пойти этим путем, потому что место, где я работаю, очень требовательно к ресурсам.

0
ответ дан 4 December 2019 в 14:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: