2016-11-22 3 views
0

В моей ViewModel есть свойство, значение которого изменено в методе DoWork для BackgroundWorker. Когда я запускаю приложение и нажимаю кнопку, которая запускает BackgroundWorker, я вижу, как изменяется значение этого свойства. Однако, когда я открываю новое окно, это свойство сохраняет свое значение по умолчанию и не обновляется, хотя BackgroundWorker все еще работает.Обновить значение свойства в другом окне в WPF

Ее это код в моем ViewModel:

private string currentData; 

... 

public ViewModel() 
    { 
     ... 

     // Property initialised with a default value 
     currentData = "BackgroundWorker is not running"; 

     ... 
    } 

public string CurrentData 
    { 
     get { return this.currentData; } 
     private set 
     { 
      if (this.currentData != value) 
      { 
       this.currentData = value; 
       this.RaisePropertyChanged("CurrentData"); 
      } 
     } 
    } 

private void DoWork(object sender, DoWorkEventArgs e) 
    { 
     isUpdating = true; 

     ... 

     this.CurrentData = "BackgroundWorker is running..."; 

     for (...) 
     { 
      ... 

      if(...) 
      { 
       this.CurrentData = "value1"; 
      } 

      else 
      { 
       this.CurrentData = "value2"; 

       ... 
      }  
     } 
    } 

RaisePropertyChanged Метод:

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

XAML-код для обоих окон (MainWindow и newtWindow):

<TextBlock Margin="10" MinWidth="250" VerticalAlignment="Center" Text="{Binding CurrentData}" FontSize="12" Foreground="White" HorizontalAlignment="Left" /> 

BackgroundWorker:

private readonly BackgroundWorker worker; 

... 

public ImageViewModel() 
    { 
     currentData = "BackgroundWorker is not running"; 

     this.worker = new BackgroundWorker(); 
     this.worker.DoWork += this.DoWork; 
     this.worker.ProgressChanged += this.ProgressChanged; 
     this.worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_Completeted); 
     this.worker.WorkerReportsProgress = true; 
    } 

Можете ли вы сказать, что я делаю неправильно, и как я могу это исправить?

+0

Существует много эллипсов (...). Вы не видите определения класса, t см. метод 'RaisePropertyChanged', и вы не видите какого-либо события. Пожалуйста, предоставьте код, который бы действительно скомпилировал, в противном случае почти невозможно, что не так. – Sefe

+0

ellipses (...) просто представляют собой множество операций, которые выполняются. так как код очень длинный – Guilian

+0

Y ou имеет экземпляр A класса Whatevs. Вы изменяете свойства экземпляра A. Если вы хотите, чтобы два окна отображали эту измененную версию экземпляра A, тогда оба окна должны иметь ссылки на экземпляр A. Как вы делитесь экземпляром между обоими окнами, зависит от вашего дизайна, который создает окна и то, как они построены. – Will

ответ

0

Вы должны создать личную ссылку строки из вашего имущества, , где свойство можно установить значение и оно будет сохранено в стеке, что-то вроде так (это как МОФ получить информацию из текстовых полей в текстовое свойство)

 private string _text; //string that is used as a reference which you can plug your new new window 

    public string Text 
    { 
     get 
     { 
      return this._text; 
     } 
     set 
     { 
      this._text = value; 
      if (null != PropertyChanged) 
      { 
       this.PropertyChanged(this, new PropertyChangedEventArgs ("Text")); 
      } 
     } 
    } 
+0

Должен ли я использовать текст для нового окна, поскольку я использовал CurrentData для MainWindow? – Guilian

0

Я бы не обновлял свойство, связанное с пользовательским интерфейсом, из фонового потока. Я не уверен, что это решит вашу проблему, но я попытаюсь использовать метод BackgroundWorker ReportProgress, чтобы уведомить вашу ViewModel об изменениях CurrentData. Затем в обработчике событий OnProgressChanged вы можете установить CurrentData в новую строку.

public void ReportProgress(int percentProgress, object userState) 

Вы можете поместить свою строку в объект «UserState».

Редактировать

что-то вроде этого:

public ViewModel() 
    { 
     ... 

     backgroundWorker.ReportsProgress = true; 
     backgroundWorker.ProgressChanged += OnProgressChanged; 

     ... 
    } 

private void DoWork(object sender, DoWorkEventArgs e) 
{ 
    isUpdating = true; 

    ... 

    ReportProgress(0,"BackgroundWorker is running..."); 

    for (...) 
    { 
     ... 

     if(...) 
     { 
      ReportProgress(0,"value1"); 
     } 

     else 
     { 
      ReportProgress(0,"value2"); 

      ... 
     }  
    } 
} 

и

private void OnProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    this.CurrentData = (string)e.UserState; 
} 
+0

Я пробовал, но porperty не обновляется в новом окне. Он сохраняет значение по умолчанию :( – Guilian

+0

Как установить DataContext нового окна? – mbger

+0

' ' – Guilian

0

ИТАК от того, что вы сказали, до сих пор мое понимание следующим образом:

С вашего оригинального вопроса:

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

Ваш комментарий к моему предыдущему ответу о настройке DataContext этого окна:

<Window.DataContext> <local:ViewModel /> </Window.DataContext> 

При создании нового окна, вы также создать новый экземпляр вашего ViewModel. Этот новый экземпляр также имеет свой собственный BackgroundWorker. Когда ты говоришь "...даже несмотря на то, что BackgroundWorker все еще запущен », то это верно только для вашего первого окна, так как сначала необходимо запустить Backgroundworker из вашего нового окна.

Если вам нужен тот же DataContext (и, следовательно, тот же BackgroundWorker) для в обоих окнах вам необходимо установить DataContext вашего нового окна на уже существующий экземпляр вашего ViewModel.

Смежные вопросы