WPF InotifyPropertyChanged and view models - wpf

So I think I'm doing something pretty basic. I know why this doesn't work, but it seems like there should be a straight foward way to make it work.
code:
private string fooImageRoot;
// ....
public BitmapImage FooImage
{
get
{
URI imageURI = new URI(Path.Combine(fooImageRoot, CurrentFooTypes.FooObject.FooImageName));
return imageURI;
}
}
So CurrentFOoTypes and FooObject also supports INotifyPropertyChanged.
So If I bind a TextBlock to CurrentFooTypes.FooObject.FooImageName, if either fooObject or FooImageName change the textblock updates. How can I subscribe my viewmodel object to recieve updates in a similiar fasion.

Correct me if I'm wrong. You want to be notified of changes to the properties FooImageName and FooObject, both owning objects use INotifyPropertyChanged to alert observers that these properties have changed.
Josh Smith had a nice article where he introduced a PropertyObserver object, which is used for just this scenario.
The MVVM Foundation includes this object as well as other helpful objects for MVVM development.
You can use the PropertyObserver, or custom code, to watch for changes in the properties you're interested in (in this case FooObject and FooImageName) and perform whatever actions you need to update the image URI based on those changes.

Related

How can I trigger some code to run in the view from the view model?

What is the best way for the view model to "ask" the view to do something, (e.g. manipulate on of the controls)? I don't think that the view model sending events violates MVVM as after all the INotifyPropertyChanged interface is an example of view models sending events to views.
I realize that having code behind in the view is not considered ideal from a MVVM perspective, so I could use an attached behavior to manipulate a particular control for example but the problem remains - how do I ask the attached behavior to do something from my view model?
I could have Boolean dependency property on my view with property changed event handler which runs the code I need to run. I could then bind this property to a property on my view model and then toggle the value of this property whenever I want to trigger the code to run. However this seems like a hack.
I could have an event on the view model and then explicitly attach this event to an event handler in the view in code but this seems anti MVVM - I should be able to achieve the connection using binding.
This must be a fairly common scenario, are there any standard solutions?
You could for example use an event aggregator or a messenger to send an event or message from the view model that the view handles in a loosely coupled way. Both the view and the view model know only about the event aggregator but they don't know anything about each other. Please refer to this blog post for more information about the concept.
Another common approach is to implement an interface in the view and inject the view model with this interface, e.g.:
public interface IDoSomething
{
void DoSomething();
}
public partial class Window1 : Window, IDoSomething
{
public Window1()
{
InitializeComponent();
DataContext = new ViewModel(this);
}
public void DoSomething()
{
//do something...
}
}
public class ViewModel
{
public ViewModel(IDoSomething doSomething)
{
//...
}
}
This doesn't break the MVVM pattern as the view model knows about and is dependant only on an interface.

A Controller for MVVM

I'm working on a WPF project that's a mishmash of code-behind xaml/xaml.cs and a few not-quite ViewModels as well.
(Disclaimer: Until recently I've had very little in the way of WPF experience. I can design and lay-out a Window or UserControl fairly proficiently, and I think I get the hang of separating an MVVM ViewModel from the View and doing binding wire-ups, but that's the limit of my experience with WPF at present.)
I've been tasked with adding some new features to the program, such that it looks like converting it to use MVVM properly first is going to be necessary.
I'll demonstrate a specific problem I'm facing:
There is a View called SettingsWindow.xaml that I'm working with. It's a set of textboxes, labels and whatnot. I've stripped-out all of the View data into a ViewModel class which resembles something like this:
class SettingsViewModel : ViewModelBase {
private String _outputDirectory;
public String OutputDirectory {
get { return _outputDirectory; }
set { SetValue( () => this.OutputDirectory, ref _outputDirectory, value) ); }
}
// `SetValue` calls `PropertyChanged` and does other common-tasks.
// Repeat for other properties, like "Int32 Timeout" and "Color FontColor"
}
In the original ViewModel class there were 2 methods: ReadFromRegistry and SaveToRegistry. The ReadFromRegistry method was called by the ViewModel's constructor, and the SaveToRegistry method was called by MainWindow.xaml.cs's code-behind like so:
private void Settings_Click(Object sender, RoutedEventArgs e) {
SettingsViewModel model = new SettingsViewModel(); // loads from registry via constructor
SettingsWindow window = new SettingsWindow();
window.Owner = this;
window.DataContext = model;
if( dialog.ShowDialog() == true ) {
model.SaveToRegistry();
}
}
...but this seems wrong to me. I thought a ViewModel should consist only of an observable data bag for binding purposes, it should not be responsible for self-population or persistence, which is the responsibility of the controller or some other orchestrator.
I've done a few days' worth of reading about MVVM, and none of the articles I've read mention a controller or where the logic for opening child-windows or saving state should go. I've seen some articles that do put that code in the ViewModels, others continue to use code-behind for this, others abstract away everything and use IService-based solutions, which is OTT for me.
Given this is a conversion project where I'll convert each Window/View individually over-time I can't really overhaul it, but where can I go from here? What does a Controller in MVVM look-like, exactly? (My apologies for the vague terminology, it's 3am :) ).
My aim with the refactoring is to separate concerns; testability is not an objective nor would it be implemented.
I personally disagree with putting much in my ViewModels beyond the stuff that is pertinent to the View (it is, after all, a model of a View!)
So I use a Controller paradigm whereby when the View tells the ViewModel to perform some action (via a Command usually) and the ViewModel uses a Command class to perfrom actions, such as saving the data, instantiating new View/Viewmodel pairs etc.
I also actually separate my ViewModel and ViewData (the ViewModel 'contains' the ViewData) so the ViewData is puirely dealing with the data, the ViewModel with some logic and command handling etc.
I wrote about it here
What you need is called Commanding in WPF.
Basically you bind Button.Command to a ICommand property in your ViewModel and when Button is clicked you get a notification in ViewModel without using code behind and casing DataContext or whathever hacks you tried.
http://msdn.microsoft.com/en-us/library/ms752308.aspx

Update One ViewModel Property from another viewmodel

I am working with MVVM application using MVVM light. Here I have 2 Views and related ViewModels like Header and Orders
public ObservableCollection<HeaderViewModel> HeaderControls
{
get { return _header ?? (_header = new ObservableCollection<HeaderViewModel>()); }
}
public ObservableCollection<object> ViewControls
{
get { return _viewControls ?? (_viewControls = new ObservableCollection<object>()); }
}
I am loading these ViewModels in observable collection to load related views.
private void LoadControls()
{
this.HeaderControls.Clear();
var headerViewModel = new HeaderViewModel();
this.HeaderControls.Add(headerViewModel);
this.ViewControls.Clear();
var orderViewModel = new OrdersViewModel();
this.ViewControls.Add(orderViewModel);
}
Now OrderViewModels have few properties like text fields, grid, those I want to update via click of icons on HeaderViewModel.
I have also tried the solution posted on, but it does not helped : Accessing Properties in other ViewModels in MVVM Light
Communication in MVVM Light between Model<->VM<->View's are normally via the Messenger class.
In short, the Messenger allows you to send a "message"(could be a string, int, pretty much any type you want) from one class to another. The receiver subscribes to receive these message(either based on type of message it wants to get or via a combination of who sends it and the type). Similarly the sender can also just send a message to a specific other class or to anyone who is subscribed to the type of the message.
One of the main advantage's of the Messenger is it's based on weak dependency hence you don't have to create a strong dependency between something like VM<->View, thereby staying true to MVVM principles. It's also well documented and you should be able to get ample help in "how to use it" from links such as:
MVVM Light - what's the Messenger?
MVVM Light Toolkit Messenger V2
or even this answer
as I've mentioned in that answer, one of the concepts shown by the download example in it is "Messenger class usage with a custom message type OpenWindowMessage". You can see how the message being sent is a custom type and how VM's subscribe/send and act on these messages.
Side-note:
From the code you've posted it's hard to say this for sure but it seems pretty weird you creating a ObservableCollection<object> ViewControls. I see you're adding a OrdersViewModel to it, so why aint the type just OrdersViewModel for the collection or even ViewModelBase. All your VM's should be inheriting from ViewModelBase anyways.

MVVM question, Event fire in the View

I am new in MVVM and WPF. so be easy with me.
I have a model (model A) in MVVM, in the ViewModel I have a collection.
The collection is present in the View as ListView.
I have another model (model B - not ui model) that need to do something every time that the listview is changing.
How can I alert model B on the selection change? What will be the right way?
By event that model A (ViewModel) will fire, and model B will catch?
By attached property of model A?
By notify property change?
By sending relay commands from model B to model A?
Use Publish /Subscriber pattern
like used in the EventAggregator
http://msdn.microsoft.com/en-us/library/ff647984.aspx
Or in the Messenger
.http://geekswithblogs.net/lbugnion/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspx
usualy MVVM frameworks ship mechanism for this build in.
Personally I would send the commands from VM to VM and make them update the Model
hope this helps
I would either
Expose an event in ViewModel A that ViewModel B can subscribe to. I would then raise that event anytime the selection changes.
Leverage INotifyPropertyChanged for notification to ViewModel B
I prefer option 1 because it makes it more obvious what you're trying to do. Plus it's more efficient (you don't have code smell of filtering on which property changed and then doing some action.)
IMHO I think relay commands should only be used as an interface between a view and a viewmodel to aid in a separation of concerns. But when you're programming from a class to a class, just use standard OOP conventions.
so pseudo code would probably look like this:
public class ViewModelA
{
public event EventHandler SelectedObjectChanged;
public IList<MyObject> ObjectList {get;set;}
public MyObject _SelectedObject;
public MyObject SelectedObject
{
get { return _SelectedObject;}
set
{
_SelectedObject = value;
if (SelectedObjectChanged != null)
SelectedObjectChanged(value);
}
}
}

WPF Collections and Databinding

I am new to WPF and trying to wrap my head around WPF's framework, what it does and does not do for you.
To clarify this, I would like to know what is the difference between this:
public List<MyCustomObject> MyCustomObjects
{
get { return (List<MyCustomObject>)GetValue(MyCustomObjectsProperty); }
set { SetValue(MyCustomObjectsProperty, value); }
}
public static readonly DependencyProperty MyCustomObjectsProperty =
DependencyProperty.Register("MyCustomObjects", typeof(List<MyCustomObject>),
typeof(Main), new UIPropertyMetadata(new List<MyCustomObject>()));
and this:
public ObservableCollection<MyCustomObject> MyCustomObjects { get; set; }
public Main ()
{
MyCustomObjects = new ObservableCollection<<MyCustomObject>();
}
Ok, we must put some order into things, there's a few concepts mixed in together here.
First of all, you're asking what the difference is between a field-backed property and a dependency property. Google would be your best friend, however I recommend this blog post by WPF's vanguard Josh Smith: Overview of dependency properties in WPF
In short: dependency properties support the richness that is WPF: Styling, animation, binding, metadata, and more.
Secondly, you're asking what the difference is between a List and an ObservableCollection. Well the latter provides change notifications (in the forms of events) on any change to the collection (addition, removal, change of order, clearing, etc.), and the former does not. You can read more about that here: The ObservableCollection Class
In short: ObservableCollection provides change notifications which are required for the UI to automatically reflect changes in the view model.
In addition to Aviad and Reed's answers, I would like to point out a serious bug in your first code sample :
public static readonly DependencyProperty MyCustomObjectsProperty =
DependencyProperty.Register("MyCustomObjects", typeof(List<MyCustomObject>),
typeof(Main), new UIPropertyMetadata(new List<MyCustomObject>()));
The new List<MyCustomObject>() used as the default value will be created only once, so by default all instances of your type will share the same List<MyCustomObject> instance, which is probably not what you want... The only sensible default value here is null
In the first case, you're setting up a Dependency Property containing a List<T> instance.
In the second, you're making a normal CLR property, but having it setup as an ObservableCollection<T>.
For WPF Data Binding, there are some differences here.
Typically, you want all of your properties in the DataContext (which is the object that, by default, things "bind" to) to either implement INotifyPropertyChanged or to be a Dependency Property. This lets the binding framework know when changes are made to that object. Normally, though, you'd only use a Dependency Property if your working with a custom control - it's usually a better idea to have your object to which your data bound be a separate class, assigned to the DataContext. (For details here, see Josh Smith on MVVM or my recent detailed post on MVVM...)
However, with a collection, you typically also want the binding system to know when the items within the collection change (ie: an item is added). ObservableCollection<T> handles this by implementing INotifyCollectionChanged.
By using the second approach (using an ObservableCollection<T>), your UI can tell when items were added or removed from the collection - not just when a new collection is assigned. This lets things work automatically, like a ListBox adding elements when a new item is added to your collection.
1:
You're using a dependency property to "tell" the framework when that property is changed. This will have the following consequences for your binding:
MyCustomObjects.Add(new MyCustomObject()); //Wont update the view through databinding
MyCustomObjects = new List<MyCustomObject>(); //Will update the view through databinding
You could gain the same databinding functionality by implementing INotifyPropertyChanged on which ever class exposes the property, but dependency properties a capable of much more than just notifying about changes. These are rather advanced features though, which you aren't likely to come across in your average joe app :)
2:
You're using an observable collection, which implements INotifyCollectionChanged for you, to tell the databinding whenever the content of the collection has changed. This will have the opposite consequences than #1:
MyCustomObjects.Add(new MyCustomObject()); //Will update the view through databinding
MyCustomObjects = new ObservableCollection<MyCustomObject>(); //Won't update the view through databinding

Resources