Reputation: 407
Im working on a WPF project in which my view model has more than 90 properties. I have a "save" button on clicking of which I save the properties to DB. Im required to disable the Save button until at lease one of the properties has been modified. I cannot go and put OnPropertyChanged event handling for each property(simply because it is too cumbersome for 90+ properties). Is there that I can do such that even if one property is changed I should get notified so that I can enable the Save button?
<StackPanel>
<StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="{x:Static res:Resources.SaveToDB}" Command="{Binding Save}" IsEnabled="{Binding CanSaveToDB}" Margin="0,0,4,0" HorizontalAlignment="Center" Style="{StaticResource OverlayDialogButtonCentered}" FontSize="14"/>
<Button Content="{x:Static res:Resources.DiscardDBSave}" Command="{Binding DiscardSave}" Margin="0,0,4,0" HorizontalAlignment="Center" Style="{StaticResource OverlayDialogButtonCentered}" FontSize="14"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView1 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View1}"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView2 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View2}"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView3 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View3}"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView4 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View4}"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView5 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View5}"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView6 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View6}"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView7 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View7}"/>
</StackPanel>
</StackPanel>
Then each of the above View has WPF controls.I have viewmodels for each of the above View. Then there is a main view model which represents above mentioned code.
Upvotes: -1
Views: 653
Reputation: 3518
Two ways come to mind.
First, you don't really need to trigger a unique property change notice in each property setter because your buttons' IsEnabled properties are not gonna be binding to any one of those 90-some odd properties in your view model. What you really want I think is to have some kind of IsDirty property that gets set whenever one of the other properties change, bind that to the IsEnabled property of the buttons, and execute the OnPropertyChanged notifier when IsDirty is changed.
If you still don't want to have to do ANYTHING special in your 90 property setters, however, the other option is to handle the change event in your view controls themselves. In all TextBoxes, for example, subscribe to TextChanged. And in your event handlers, set the IsDirty property on your view model. (You can subscribe to those handlers in the controls' styles so you don't have to set the event handler 90 times.)
Barring those two ideas, I don't think there's any way to do what you want. There's no built in mechanism in C# to get notified when a class property has changed. You're gonna have to intercept the change yourself, if not in the properties' setters, then using event handlers on the controls they're bound to.
Upvotes: 0
Reputation: 1424
A typical solution is to implement it just once (usually on a base class) and call it from the setter on each property passing the name of the property that has changed. This is still relatively cumbersome. Another approach is to use a tool such as Fody to automatically add this logic.
If all your properties are calling a single OnPropertyChanged
implementation then the logic to set the dirty flag (and so enable the Save button) can be implemented there.
Upvotes: 1
Reputation: 1947
As per the Documentation,
The PropertyChanged event can indicate all properties on the object have changed by using either null or String.Empty as the property name in the PropertyChangedEventArgs.
Upvotes: 0