Binding a viewmodel's property to another's - wpf

I have a main window coupled with a view model.This main window uses a usercontrol which also has its own viewmodel.
What I would like to achieve is setting a binding in the main window's xaml between one of its viewmodel's custom property and one of the usercontrol's viewmodel's custom property.
How would one go about doing that?

Could you instead use the ViewModels as projections of a Model?
That is, could you have a class that holds the state (or actions) that both the VMs need to expose and have both the VMs reference this class?
If for some reason you have to couple views to something outside their own DataContext I believe you can only go up the visual tree by using RelativeSource FindAncestor in the binding. I don't think you can traverse down (e.g. Window -> Control).

If you really want to Bind them together you could make your ViewModel's properties Dependency Properties and your ViewModel derive from DependencyObject - then you could do..
var binding = new Binding("Something");
binding.Source = myViewModel1;
binding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(viewModel2,ViewModelType.SomethingProperty,binding);
If this is a good design having your viewmodels derive from DependencyObject is another question..
You could also try looking at this library that allows binding to and from POCOs.

I ended up not using a modelview for my usercontrol, not as neat but at least it works and is less complicated datacontext wise.
Thanks to all.

Related

How do I bind wpf with specific datacontext from different classes?

Hi guys I am very new to WPF. I have two datacontexts in two different classes which are being binded by the elements in the View producing datatriggers, and one or the other wouldn't work as they cannot bind both datacontexts together. How do I bind xaml from two different classes using datacontext? Is there any alternative way could make it easier?
Class A
public Window1()
{
InitializeComponent();
Appointments = new Appointments();
DataContext = Appointments;
}
Class B
private void FilterAppointments()
{
this.DataContext = this;
...
Firstly, you should never use DataContext = this; in any UserControl in a serious WPF Application. Secondly, you should look up the MVVM design pattern, which provides the idea of a view model for each view. Your Window or UserControl are the 'Views' and your view models are simply classes that contain all of the data properties that you need to display in your view.
Therefore, you should declare a view model class (that implements the INotifyPropertyChanged interface) and put whatever you wanted to data bind into that. Finally, you should set that object as the DataContext property value. In that way, you'll have access to all the data that you need.
Looking again at your question, it just occurred to me that you may have set the DataContext to this so that you could use properties that you declared in your Window or UserControl. If this is the case, then you should not set the DataContext to this, instead using a RelativeSource Binding to access the properties. That would free up the actual DataContext to be set however you like. Try this Binding within the Window or UserControl:
<TextBlock Text="{Binding PropertyName, RelativeSource={RelativeSource
AncestorType={x:Type YourPrefix:YourWindowOrControl}}}" />

WPF does not rebind if new datacontext Equals() previous datacontext

As explained on http://www.lhotka.net/weblog/DataRefreshInWPF.aspx
A WPF control sometimes does not rebind to the new datacontext. Specifically when using viewmodels that implement Object.Equals to see if viewmodels are logically equal. The problem here is that the control does not rebind to the new datacontext if it is logically equal to the previous. This causes the controls to become limp, they are not bound to the new viewmodel.
I circumvented this by first setting the DataContext to a new object(). This makes sure the control rebinds to the new datacontext. This does not work however when a viewmodel contains another viewmodel that implements Object.Equals. A view bound to that viewmodel using a DataTemplate will not rebind. How can I work around this?
Obviously WPF databinding should use ReferenceEquals instead of Equals..
UPDATE: I solved it for now by having the sub ViewModels implement IEquatable<T> instead of overriding Object.Equals.
I solved it for now by having the sub ViewModels implement IEquatable instead of overriding Object.Equals.

Can I have a MVVM model inherited from an other model?

I have a ProductViewModel class which contains different properties.
Then I have a ProductDetailsViewModel class which inherit from ProducViewModel class. The reason I am doing it this way is in order to get correct binding environement and avoid duplication of properties from previous view.
I am allowed to do this or each ViewModel should be clearly isolated?
Through code I can acess the properties of the ProductViewModel class from ProductDetailsViewModel view but when I set the datacontext of my ProductDetailView to ProducDetailsViewModel class and bind properties URI for instance which is define inside the inherited class, binding seems not occurs.
Any idea ?
You can do this too, but i think maybe better would be to separate them and use Dependency Injection.
You create and interface for your ProductViewModel and implement it and then you inject this into your ProductDetailsViewModel.
MVVM + WPF + DI
MSDN DI
Yes this is fine, and I do this all the time in my WPF projects so it should just work. Some suggestions:
Can you check your output window when debugging the application. Are there any binding errors suggesting a mis-typed xaml binding?
Are you using any DataTemplates in xaml which bind to a specific type, e.g. ProductViewModel not ProductDetailsViewModel?
Does the base type (ProductViewModel) implement INotifyPropertyChanged?
Are all the properties in ProductViewModel and ProductSetailsViewModel raising the PropertyChanged event with directly typed string property name?
Best regards,

Custom control, View Model and dependency properties

I'm creating custom control and because I need to do lot's of binding inside a style/template it makes perfect sense to go with MVVM. Where do I declare dependency properties then?
Do they stay in control class? How do I link them to VM?
See my answer to your other question about custom controls and view models. Here's the short version:
Custom controls shouldn't have view models.Don't set the data context of your own control. That's reserved for the consumer.All of your dependency properties should be declared in your MyCustomControl.cs file.Use TemplateBinding in your genric.xaml because it's more efficient that Binding.
To put it another way, what's the view model for a Border or a Button? Answer: they don't have one because they're just controls. UserControls have view models, but controls just present and interact with the data which you give them (where? In your UserControl). Custom control development is probably the hardest thing for a seasoned MVVM developer: your reflex is to make a view model, but that reflex is unfortunately wrong. I know because I've made this mistake myself.
Dependency Properties could be delared in the Control they are belongs to.
When following MVVM in WPF/Silverlight the common approach is to set ViewModel as DataContext of the appropriate View. So you would be able to link custom Dependency Properties to the ViewModel properties using Bindings in XAML.
Let's assume you already set ViewMosel to DataContext of the View:
var view = new UserView
{
DataContext = new UserViewModel { Name = "Custom Name" }
};
public class UserViewModel
{
string Name { get; set; }
}
UserView.xaml:
<TextBlock Text="{Binding Name}" />
When creating a custom control, the control itself is a view model. Declare dependency properties on it to expose bindings that users of the custom control can leverage. For example if you have a timeline control, you might have properties like StartDate and EndDate on the control exposed as dependency properties. Your Controls Default Template would make template bindings to the dependency properties. A consumer of your control might then have a project timeline viewmodel that he binds to the properties on the control.
The primary purpose of a custom control is to provide behavior and a default look and feel for that behavior which is easy to override (by providing a new template). Hope this helps.

Can MVVM Usercontrols have property defined in codebehind?

I have a WPF user control ...which is in MVVM. The user control(which contains a listview) need data from the page (where it is included). I have to set a property to get this data input. Will this comply with MVVM...if not, what is the way for the same?
I'm afraid this won't be correct in MVVM design pattern. try to stick to your view model to define properties. Why don't you consider moving that property to control's vm?
Use an ObservableCollection rather.
ObservableCollection<myModel> myOC = new ObservableCollection<myModel>();
where myModel is a class that has to be constructed transforming your columns in the DataTable to Properties.
In your MainViewModel, loop through the DataReader and create myOC out of it.
Now bind myOC to a ListView in your page.
The DataTemplate of ListView should be a view(UserControl) drawing data from a ViewModel constructed out of myModel
But your UserControl has the entire ListView inside. If that is on purpose, then let me know the entire design to give a better idea.

Resources