Custom DependencyProperty not updating external view model - wpf

I have a UserControl that has a DataGrid in it filled with members. The DataGrid.ItemsSource is bound to an ObservableCollection on the model. The DataGrid.SelectedItem is bound to the SelectedMember field on the model. The SelectedMember._set calls NotifyPropertyChanged and the event calls SetValue() for the exposed DependencyProperty.
This UserControl is on a page. That page has a viewmodel too. I'm trying to bind the UserControl.CurrentMember to the viewmodel.SelectedMember but it's not changing. I can bind the CurrentMember.MemberName to a textbox and the box fills with the member name so it looks like the UserControl is exposing the DependencyProperty correctly. But if I bind to the model it doesn't update.
I can't find any cross bindings. The bind to the TextBox works fine. The field on the page model is new so there's nothing bound to it.
What could be the problem? Does the field on the page model need to be a DependencyProperty? The compiler would give me an error if that were the case.
I'll try and get a code sample but it's so ingrained I can't just post a couple of lines of code.
Tom P.

After combing the code and trying to replicate the problem in a new project I found the problem.
In the UserControl I set the DataContext to the Model. But the UserControl.DataContext gets overwritten when I put it on the page. What i needed to do was name the MainGrid and set the DataContext of the MainGrid to the UserControlModel. MainGrid, being private to the UserControl, won't get overwritten. Now it works wonderfully.

Related

Getting BindingExpression path error in output window, but bindings work fine

In out project, we use MVVM and WPF.
To bind View and View Model, we use another class and call it presenter. This presenter class binds View and View model, so we can bind view to different view models. I am setting Data context of view to viewmodel inside this class.
class presenter
{
// in constructor or any method
ViewModel = new ViewModelCls();
View = new ViewXAMLName();
View.DataContext = ViewModel;
}
Now, the problem is, I am using ContentControl in one window, say abc.xaml and setting its content to presenter.View.
<ContentControl Content="{Binding SelectedOption.Presenter.View}"></ContentControl>
When I run my project, all binding works fine and Presenter.View gets populated with Presenter.ViewModel. But in output window, I can see many binding errors for the properties present in Presenter.ViewModel.
I tried to debug and found out that for SelectedOption.Presenter.View, it sets DataContext to ViewModel of abc.xaml and tries to find properties in that View model. But obviously, it cannot find it and writes all those binding error in output window. Later on, it sets the VM to the "Presenter.ViewModel" and everything works fine.
Is there any way to remove those Binding errors from Output window??
Thanks in advance!!
The Data Binding errors can be suppressed by setting the binding source level to Critical.
System.Diagnostics.PresentationTraceSources.DataBindingSource.Switch.Level = System.Diagnostics.SourceLevels.Critical;
More information on this.

Refresh a DataGrid in the MVVM pattern

I have a View with a dataGrid. This datagrid bind a property in the ViewModel that is an ObservableCollection.
I edit some data in the dataGrid, and a field is updated by code, because it depends on some operations. Well, if I check the item in the observable collection, I can see that all the data is correct, but the info in the dataGrid is no refresh.
I want to force the refresh because I know that the observableCollection only raise the change property event when I add o remove items, but not if I edit one of them.
Because I am use Entity Framework 4.1, really the ItemsSource of the dataGrid is the local of the DbSet, so I don't know how to implement the notifyPorpertyChanged in the classes of the model edmx, and I am looking for an alternative, like to force refresh the dataGrid.
Because the property of the ViewModel that I use to bing the ItemsSource of the dataGrid is a reference to the local, I mean that to set the property I do myProperty = myContext.MyTable.Local and that raise the event PropertyChanged that I implement in my ViewModel, I try to do myProperty = myContext.MyTable.Local again to try to raise the event and force the refresh of the dataGrid, but it does not work.
What alternatives do I have?
Make sure that you have the Binding Mode set to TwoWay. Implement in the set portion of your property OnPropertyChanged and the rest should take care of itself.

How can I easily expose bindable properties of nested controls from a custom UserControl?

My first question here on the Stack. Forgive me for the bad explanation in advance.
I am working on my first MVVM application (Silverlight). I have a custom user control that contains a ListBox to show navigation items. This control is placed in my main xaml page. I don't know if I need to create a composite view model (my main page view model) with a view model especially for the custom control in it or if there is some way to elevate the ListBox properties that I need to bind to.
Through XAML I don't know how to bind, let's say, the ItemsSource property of the ListBox inside the custom control to my main page viewmodel. Basically, I'm at the point that I am questioning my design decision for trying to bind the custom control through my main page view model.
What I have done so far is create dependency properties for the custom control and try to tunnel those dependency properties down to the ListBox properties. I've achieved success with this method for ItemsSource but am having issues with SelectedItem.
Even if I do get SelectedItem to work, it still feels Wrong. Thanks for any advice in advance.
The UserControl should inherit the DataContext from its parent control, unless you are setting it directly. You can then bind to the properties on your view model from your UserControl.
If you would like to create a ViewModel specifically for the UserControl, you can also do that. You would then expose it as a property on your main ViewModel, and bind to it in the MainPage. Example:
public class MainViewModel
{
public ChildViewModel ChildInfo { get; private set; }
}
And then in the view:
<Grid>
...
<lcl:ChildView DataContext="{Binding ChildInfo}" />
...
</Grid>
Your ChildViewModel would then contain properties like SelectedItem to bind your ListBox to.

ViewModelLocator.LocateForView returns new Model, not the model ContentControl is bound

I have a ContentControl in xaml defined as:
<ContentControl Micro:View.Model="{Binding ProductionGrid}" />
I use the View.Model as the control is embedded in a docking panel.
My ViewModel has the property defined and it set in the constructor of the ViewModel and uses constructor injection to create the instance.
The View gets instantiated, but I cannot access the model that was created in the ViewModel, it seems to create a new model when trying to get the instance from the xaml.cs constructor of the View.
var model = Caliburn.Micro.ViewModelLocator.LocateForView(this) as DynamicDataGridViewModel;
How can I correctly get the model that should be associated with the View when it's created?
If the ContentControl is embedded in a docking panel you can just name the ContentControl x:Name="ProductionGrid" and shouldn't need Micro:View.Model="{Binding ProductionGrid}"
The View gets instantiated, but I cannot access the model that was
created in the ViewModel, it seems to create a new model when trying
to get the instance from the xaml.cs constructor of the View.
You mean the ViewModel gets instantiated?
So the binding works? I'd have to look but I don't know if CM will find ProductionGridView from ProductionGrid, it might, I'm not sure. ProductionGridViewModel and ProductionGridView would work.
You shouldn't need to code anything in the xaml.cs constructor, in fact, I delete the xaml.cs files.

"Nested" MVVM Question

I have a WPF window that has a datagrid and a user control for a form for the fields in that datagrid. The user control and the WPF window have view models.
The user control's DataContext is bound to one of the window's view model's member field, whose value changes during the data grid's Selection Changed event.
I'm not sure if this is the right way to do it because I am unable to create references from the inner view model to the outer view model for some reason. Constructor injection won't work because I'm required to use default constructor only, and I can't seem to put a property injector in the right place (always getting null reference when I try to use it).
I am also unable to get my property change notification to work properly in the inner view model.
Is there a better way to wire my view models so that they automatically change the values in the user control when a new row is selected in the datagrid? I have a feeling that binding to the control's DataContext is not the way to go.
This doesn't seems a complex/nested scenario. Looks like pretty much a normal master details scenario. Suppose you want to edit Customer data, I would have an ObservableCollection instance bind to the DataGrid, and there will be a SelectedCustomer property in the VM also. In the DataGrid you can set SelectedItem twoway bind to the SelectedCustomer property which makes SelectedCustomer always updated with your selection. Since the usercontrol has the same instance of customer as in the DataGrid row, whenever you change anything in the UC those data will get reflected in the grid. Ofcourse all those properties should fire NotifypropertyChanged.

Resources