1

After a major edit to this quesiton, I'm hoping it's now clear.

I'm very lost with binding in WPF when 1 change should affect multiple properties.

I regularly use VVM to bind my ViewModel to my View and I would say I'm OK with it.

I am trying to implement a state controller. This means that, what ever settings I made in part of my UI, the reflection is through out.

For example in my part of my UI, I can toggle a feature on or off, such as "show images"

When I make this change, I'd like everything in my application to be notified and act accordingly.

So, my StateController class will have a property

public bool ShowImages 

And in my View, I'd likely have something like

<image Visible ="{Binding ShowImages", Converter={StaticConverter ConvertMe}}" /> 

The problem I have is how I go about making the StateController alert all of my ViewModels of this.

Currently, in each ViewModel I'm assuming I'd have to have the same property repeated

public bool ShowImages 

EG

public class StateController : BaseViewModel { public bool ShowImages{get;set;}//imagine the implementation is here } public class ViewModelB : BaseViewModel { public bool ShowImages{}//imagine the implementation is here } public class ViewModelB : BaseViewModel { public bool ShowImages{}//imagine the implementation is here } 

So, my question is, if I updated ViewModelB.ShowImages, how would I first inform the StateController which in turn updates all ViewModels.

Is this something the INotifyPropertyChanged can do automatically for me since they all share the same propertyName, or do I have to implement the logic manually, eg

public static class StateController { public bool ShowImages{get;set;}//imagine the implementation is here } public class ViewModelA : BaseViewModel { public bool ShowImages { get { return StateController.ShowImages; } set { StateControllerShowImages = value; OnPropertyChanged("ShowImages"); } } } public class ViewModelB : BaseViewModel { public bool ShowImages { get { return StateController.ShowImages; } set { StateControllerShowImages = value; OnPropertyChanged("ShowImages"); } } } 

I hate the idea of the above implementation but it does show what I'm trying to achieve. I just hope there is a better way!

5
  • You have two different objects, change prop of one of them. How does the WPF should know that this objects have the same business role? Commented Jun 19, 2014 at 14:09
  • I recall writing an answer recently about sharing a property between two classes using a Singleton. Is that what you're looking to do? Commented Jun 19, 2014 at 14:14
  • You should notify your View about changes. If you have two independent props referring the same datamodel obj, you should change your model and then call RaisePropertyChanged for both props to make WPF re-read them. Commented Jun 19, 2014 at 14:16
  • @Rachel, I don't think so. May be if I said I'm trying to implement a StateController it is easier to understsand. In that there are many places where the configuration can be changed, these should alert the StateController which will then inform all ViewModels and they update accordingly... Commented Jun 19, 2014 at 14:18
  • 1
    I have to confess that I couldn't understand what this question is about, but all I can do is advise that you read the Data Binding Overview page on MSDN. This page is a great resource and extensively covers a very wide number of data binding issues. Hopefully after reading it, you'll be able to answer your own question. Commented Jun 19, 2014 at 14:19

4 Answers 4

1

The PropertyChange notification is only raised for that one object model.

So raising a change notification of the "Name" property of ClassA will only update the UI in cases where it's bound to that specific ClassA.Name. It won't trigger a change notification for any ClassB.Name, or other instances of ClassA.Name.

I would suggest using a Singleton here for your StateModel, and having your other models subscribe to the StateModel.PropertyChanged event to know if it should update, like this answer.

public ViewModelA { public ViewModelA() { StateController.Instance.PropertyChanged += StateController_PropertyChanged; } void StateController_PropertyChanged(object sender, NotifyPropertyChangedEventArgs e) { // if singleton's ShowImages property changed, raise change // notification for this class's ShowImages property too if (e.PropertyName == "ShowImages") OnPropertyChanged("ShowImages"); } public bool ShowImages { get { return StateController.Instance.ShowImages; } set { StateController.Instance.ShowImages = value; } } } 
Sign up to request clarification or add additional context in comments.

2 Comments

So raising a change notification of the "Name" property of ClassA will only update the UI in cases where it's bound to that specific ClassA.Name I was told differently - this is the perfect answer!
I just want to point out the memory leak in this example. ViewModelA would need to be disposable and unbind from the PropertyChanged event on dispose.
1

To avoid code repetition you can create a class derived from BaseViewModel that implements your property and have ViewModelA, ViewModelB extend it. However, this does not solve the problem of keeping each instance updated.

In order to do so, you may:

  • Use a static class (your current solution) or a Singleton as suggested in one of the comments. This is simple but has potential problems such as race conditions and coupling.
  • Have your ShowImages binding property repeated in each ViewModel and update it by subscribing to a ShowImagesChanged event. This could be published through a Command executed from the UI. I'd say this is the WPF approach and has the benefit of decoupling the ShowImages state management from its consumption.
  • Assign the ShowImagesupdate responsibility to a single ViewModel and subscribe to the its PropertyChanged in the other ViewModels so that they update accordingly. Better than the first option, but still huge coupling.

6 Comments

Ah, the 2nd bullet point is very interesting ... But I'm not sure what the properties would be subscribing too. What would the new event do that the INotifyProeprtyChanged doesn't do?
@MyDaftQuestions I added a third option which I think would be what you suggest. In that option, you still can take advance of the Command but the downside is that in order to use INotifyPropertyChanged you need a reference to the ViewModel you are subscribing to. That is what you gain by using an event aggregator instead.
I have a bad feeling about all these event subscribtions. That can easiliy lead to bad and hard to find memory leaks if you are not careful.
I wouldn't use subscriptions except in cases where two completely unrelated objects need to talk to each other. In this scenario dealing with configuration properties, I think a shared StateController is probably a better option, as I answered here
@JensH I do share your bad feeling regarding .NET events and leaks with references, but I'm referring to the event aggregator pattern.
|
1

If I understood you correctly, you are looking for a mechanism that allows your different ViewModels to communicate between each other.

One possible way would be to implement the Observer Pattern (a code example can be found here: "Observer pattern with C# 4"). In this way your ViewModel subscribe each other to receive change notifications from a "publisher", i.e. the ViewModel that had its value changed. You have a good control over who receives which notification from which publisher. The downside of this approach is a tight coupling between your models.

My approach would be this:

Use a message dispatcher. Your ViewModels can subscribe to a certain type of message, e.g. ShowImagesChanged. If any of your ViewModels changed the ShowImages property, that ViewModel calls the dispatcher to send out such a ShowImagesChanged message with your current values.

This way you can keep you ViewModels decoupled from each other. Still, although the ViewModels do not know each other this gives a way to exchange data between them.

Personally, I have used the Caliburn Micro MVVM framework several times for this, but there should be enough other MVVM frameworks that provide the same functionality to fit your taste.

The Calibiurn Micro documentation and how easily the dispatcher can be used is here: Event Aggregator

2 Comments

I keep seeing the observer pattern and event aggregator but yet to find motivation to learn something else until I get my head around the basics. +1 and thank you
@MyDaftQuestions, I think design patterns ARE basics. They are time tested solutions to problems that need to be solved in programming over and over again. As design patterns have proved to be well working solutions I strongly recommend learning their underlying principles and to learn from THEM. I wish somebody had told about them when I was starting out that would have saved a lot of my nerves. :-)
0

Why repeat properties at all? Just bind to StateController itself. Say we have singleton StateController:

public class StateController : INotifyPropertyChanged { private static StateController instance; public static StateController Instance { get { return instance ?? (instance = new StateController()); } } //here`s our flag private bool isSomething; public bool IsSomething { get { return isSomething; } set { isSomething = value; PropertyChanged(this, new PropertyChangedEventArgs("IsSomething")); } } private StateController(){} public event PropertyChangedEventHandler PropertyChanged = delegate { }; } 

Then in base VM class just make a reference to this controller:

public StateController Controller { get { return StateController.Instance; } } 

And where needed bind like this:

<CheckBox IsChecked="{Binding Controller.IsSomething}"> Test </CheckBox> 

This way every binding will work with one property and react to one property. If you need some custom code to work you can subscribe to PropertyChanged of StateController where needed and take action.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.