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

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.

Related

WPF Prism Unity Container. Setting keyboard focus on usercontrol or usercontrol grid parent

I'm working on a project that utilizes WPF, using the Prism library and Unity Container.
I have a mainwindow, which contains a mainviewmodel control which in turn is populated by a collection of user controls.
My goal is to set keyboard focus to the mainviewmodel where I have an EventTrigger InvokeCommandAction which reacts to keyeventsargs...
Currently the only way the command is fired if I use a textbox within the control (or child controls). My goal is to have the mainviewmodel control or grid get and preserve keyboard focus.
Any tips would be appreciated!
//Nathan
Either not understanding your question correctly or you should review the basic concepts of MVVM in a WPF implementation.
The View is the WPF controls.
WPF Window/UserControl files contain WPF markup which is the View.
Controls in a view leverage DataBindings to the DataContext property of either the control itself or the parent containing control (which it will inherit).
DataContext property is set to an instance of an object that is the ViewModel. It contains properties to hold values and commands to execute actions.
So conceptually there is no "mainviewmodel control", there is a MainView which contains controls and may in this case have its DataContext property set to an instance o MainViewModel. (hence my confusion)
Finally, while it is possible and some might even recommend writing UI rules/logic in a view model I haven't found much benefit in it.
You are much better off putting UI logic in the XAML or in the MinView code behind. You can still access the MainViewModel in the code behind by casting the MainView.DataContext property as a MainViewModel.
So for example:
MainView.KeyDown event can be wired up to call MainViewModel.CommandX.Execute();

Binding a viewmodel's property to another's

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.

How to manipulate WPF window controls (tabs, textboxes, listboxes) from a ViewModel

I'm kinda new to WPF. I'm making an app using WPF (all the UI controls are already fixed) and MVVM but most of the events are in the code-behind. I'm in the process of clearing the code-behind but I have codes like (the ones below) to switch through tabs, and to trigger visibility of controls depending on parameters:
tabItem1.Selected = true;
textBox1.Visibility = Visibility.Hidden;
lbxHusbandsWives.Items.Add(txtHusbandsWives.Text + '/' +
cbxHusbandsWivesCountry.Text + '/' +
dpHusbandsWives.SelectedDate.Value.ToShortDateString());
How can I do that in the viewmodel? Well, inside a Command? So I can clear the messy code-behind? Thanks for your help. :)
As I said many times before, MVVM doesn't mean "no code behind". There are things that you can or should do in code-behind, as long as they are strictly related to the view and are not necessary for the ViewModel to work properly.
That being said, in most cases you don't need to do anything in code-behind. You normally use bindings to control the view from the ViewModel. This allows the ViewModel to be completely ignorant of the view: it just exposes properties that the view can access, and sends notifications when the values of the properties change. The ViewModel should definitely not manipulate the view or its components.
Everything in the code you posted can be done with bindings in XAML:
textBox1.Visibility can be bound to a bool property of the ViewModel, using a BooleanToVisibilityConverter
lbxHusbandsWives.ItemsSource can be bound to an ObservableCollection in the ViewModel (an ObservableCollection notifies the view when items are added to or removed from it)
txtHusbandsWives.Text, cbxHusbandsWivesCountry.Text and dpHusbandsWives.SelectedDate can also be bound to properties of the appropriate type

Dynamically specify and change a Silverlight DataGrid's columns during runtime (MVVM)

What's the best method of dynamically specifying DataGrid columns in the Silverlight DataGrid control at runtime following the MVVM pattern?
What I'd like to do would be bind the "DataGrid.Columns" property to a property in my ViewModel so that, if the user adds/removes columns, I simply update the ViewModel property and the DataGrid would change. Problem is, the "DataGrid.Columns" property can't be bound to (I don't think).
Because this property isn't available nor is the DataGrid control itself available at the ViewModel level, my current approach is to step outside of the MVVM pattern for this particular implementation and capture certain events in View's code-behind using MVVM Light's Messenger class and then talk directly with the DataGrid control to achieve this capability. I know this is a general statement to this approach without details but is there an easier way... or maybe not so much easier, but a better way that adheres to the MVVM pattern a little better?
It's driving me crazy that the DataGrid control's Columns property can't be bound... seems like such a simple thing.
FYI - Before it's suggested to use AutoGenerateColumns = True, the class being bound for each item in the collection that's bound to DataGrid.ItemsSource does not have individual properties to identify what is bound to the columns... it's a collection property that contains the columns in order to keep them completely dynamic so that particular path is out. Also, handling the AutoGeneratingColumns and using e.Cancel to show/hide columns is also iffy for this same reason (I think).
I agree that it is a pain that DataGrid.Columns cannot be bound to. My recommendation here would be to define your columns in the ViewModel in an ObservableCollection. In the View (code behind), handle the CollectionChanged event of this ObservableCollection, and modify the DataGrid.Columns in code.
While this solution is less elegant, it is straightforward. For your ViewModel, you can unit test that the CollectionChanged event is raised properly when columns are added, removed or moved. The View code cannot be tested, so I guess this is something you need to live with. The advantage is that, if some day the DataGrid.Columns property can be databound, it will be easy to refactor this to remove the code behind.
Another way (I think) would be to create an attached behavior or a Blend behavior to take care of this. Attach it to the DataGrid; instead of binding to the DataGrid.Columns directly, bind to a property on the behavior, and have the behavior modify the DataGrid (the AssociatedObect) directly.
Does that make sense?
Cheers,
Laurent

MVVM Update binding issue

I have user control to which I bind a viewmodel, this implements the INotifyPropertyChanged, thru the datacontext, this has a property that is a IList that I bind to the itemsdatasource of a grid, then on the code, in another class I add some values to the list, but the UI doesn't reflect this change although in debug I can see that the datagrid has this items added but they don't appear in the UI, can anybody help me, I can't see what is the problem.
ObservableCollection<T> is your friend. It implements INotifyCollectionChanged, saving you the trouble.

Resources