2015-03-24 1 views
0

У меня есть видимость индикатора выполнения, привязанный к следующему свойству в моем ViewModel:Как уведомить связанный элемент о изменении значения, когда значение происходит из модели?

public string CalcProgVisibility 
{ 
    get 
    { 
     return Calculation.CalcProgVisibility; 
    } 
    set 
    { 

    } 
} 

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

EDIT:

Вот это свойство в моей модели тоже. Я использую onpropertychanged, но это не делает его вид.

Я изменяю значение в модели, представление привязано к моей модели просмотра, а viewmodel si пытается вернуть значение, взятое из модели. Я обновляю значение на модели и не могу подтолкнуть факт, что он обновил значение вплоть до представления, я могу получить только режим просмотра, чтобы увидеть, что он изменился ...

+1

Не можете просто послать событие в вашей модели, когда свойства изменяются? Вы уже это пробовали? – SuperOli

+0

Никто не останавливает вас от реализации объекта «INotifyPropertyChanged» в объектах модели - http://stackoverflow.com/questions/6922130/in-mvvm-model-should-the-model-implement-inotifypropertychanged-interface. –

+0

Поднять уведомление об изменении свойства https://msdn.microsoft.com/en-us/library/ms743695%28v=vs.110%29.aspx –

ответ

1

Я обновил все код. Надеюсь, теперь это ясно.

Определите управления BindingMode = TwoWay

<TextBox Visibility="{Binding Path=CalcProgVisibility, Mode=TwoWay}"... 

и вызвать OnPropertyChanged метод на сеттер свойства в модели представления, а также в модели

 //Model 
    public class Calculation : INotifyPropertyChanged 
    { 
     private string _calcProgVisibility; 

     public string CalcProgVisibility 
     { 
      get { return _calcProgVisibility; } 
      set 
      { 
       _calcProgVisibility = value; 
       OnPropertyChanged("CalcProgVisibility"); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     protected void OnPropertyChanged(string propertyName) 
     { 
      RaisePropertyChanged(propertyName); 
     } 

     private void RaisePropertyChanged(string propertyName) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 

      if (handler == null) return; 

      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    //ViewModel 
    public class ViewModel : INotifyPropertyChanged 
    { 
     public ViewModel(Calculation model) 
     { 
      this.CalcProgVisibility = model.CalcProgVisibility; 
      model.PropertyChanged += (s, e) => UpdateEntity(s as Calculation); 
     } 

     private void UpdateEntity(Calculation source) 
     { 
      CalcProgVisibility = source.CalcProgVisibility; 
     }  

     private string _calcProgVisibility; 

     public string CalcProgVisibility 
     { 
      get { return _calcProgVisibility; } 
      set 
      { 
       _calcProgVisibility = value; 
       OnPropertyChanged("CalcProgVisibility"); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     protected void OnPropertyChanged(string propertyName) 
     { 
      RaisePropertyChanged(propertyName); 
     } 

     private void RaisePropertyChanged(string propertyName) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 

      if (handler == null) return; 

      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
+0

Представление привязано к viewmodel, но viewmodel возвращает переменную из модели, и эта переменная постоянно обновляется внутри модели. Я пробовал это, но он не будет обновляться ... – pingu2k4

+0

Этот код вызывает только обновление пользовательского интерфейса, когда изменяется свойство «InstallationOrderVisibility». Как и другие комментарии, ваши модели должны также реализовать INotifyPropertyChanged, чтобы уведомить viewmodel. –

+0

Этот код не относится к тому, что у меня есть ... Этот код возвращает частный bool, локальный для того же класса, тогда как у меня есть возвращаемое публичное свойство из другого класса. Свойство изменяется в другом классе. Поэтому вместо «return_installOrderVisibility» должно быть «return calc.propertyName;», где calc ссылается на другой класс (моя модель).propertyName - единственное фактическое значение, которое когда-либо изменяется. – pingu2k4

1

Ваш ViewModel должен осуществлять Интерфейс INotifyPropertyChanged. Чтобы запустить его в вашем случае, ваша модель просмотра также должна знать об изменениях в объекте модели. Таким образом, ваш объект модели также может реализовать INotifyPropertyChanged или использовать какую-либо форму шаблона наблюдателя.

Если ваша модель реализует INotifyPropertyChanged, ваша модель просмотра должна вручную зарегистрироваться для этого события и реализовать обработчик. Это может, в свою очередь, вызвать событие PropertyChange для viewmodel.

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

Первое решение может выглядеть следующим образом:

using Microsoft.VisualStudio.TestTools.UnitTesting; 
using System.ComponentModel; 
using System.Runtime.CompilerServices; 

namespace StackOverflow 
{ 
    [TestClass] 
    public class IntegrationTest 
    { 
     [TestMethod] 
     public void NotifyPropertyChangeShouldFireOnViewModelWhenModelChanges() 
     { 
      //Arrange 

      Model model = new Model(); 
      ViewModel sut = new ViewModel(model); 
      bool notifyPropertyChangeOnViewModelWasCalled = false; 
      sut.PropertyChanged += (sender, e) => { notifyPropertyChangeOnViewModelWasCalled = true; }; 

      //Act 

      model.CalcValue = 4711; 

      //Assert 

      Assert.IsTrue(notifyPropertyChangeOnViewModelWasCalled, "NotifyPropertyChange was not fired on ViewModel"); 
     } 
    } 


    public class ObjectWithNotifyPropertyChanged : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 
     protected void RaisePropertyChanged([CallerMemberName]string propertyName = "") 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 

    public class Model : ObjectWithNotifyPropertyChanged 
    { 
     private double calcValue; 
     public double CalcValue 
     { 
      get 
      { 
       return calcValue; 
      } 
      set 
      { 
       if (calcValue != value) 
       { 
        calcValue = value; 
        RaisePropertyChanged(); 
       } 
      } 
     } 
    } 

    public class ViewModel : ObjectWithNotifyPropertyChanged 
    { 
     public ViewModel(Model model) 
     { 
      this.model = model; 
      model.PropertyChanged += model_PropertyChanged; 
     } 

     void model_PropertyChanged(object sender, PropertyChangedEventArgs e) 
     { 
      switch (e.PropertyName) 
      { 
       case "CalcValue": 
        RaisePropertyChanged("CalcValue"); 
        break; 
      } 
     } 

     private Model model; 

     public double CalcValue 
     { 
      get 
      { 
       return model.CalcValue; 
      } 
     } 
    } 
} 
+0

С моей моделью представления, реализующей событие onpropertychanged, ничего не делает, поскольку переменная только когда-либо устанавливается изнутри модели, а не внутри viewmodel. Я положил onpropertychanged событие на модель, но это не делает его для представления. – pingu2k4

+0

Я попытался немного разъяснить это в моем anser. Просто внедрение INotifyPropertyChanged в вашей модели ничего не делает. Ваша модель просмотра должна регистрировать обработчик для этого события и делегировать его на свое собственное событие changechange, если это необходимо. –

+0

ОК, это имеет смысл :), но я понятия не имею, как это сделать ... Как мне это сделать? Спасибо – pingu2k4

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