Reputation: 6816
I've refactored my WPF application so that the DataContexts are no longer instances of some class that implements INotifyPropertyChanged
but rather some custom interfaces of mine. The object that implements each custom interface is required to also implement INotifyPropertyChanged
. But I can no longer enforce this requirement at build time. I'm not sure if this is a good idea.
For example, consider the following simple class hierarchy
// Base view model class has stock implementation of INotifyPropertyChanged.
public BaseViewModel : INotifyPropertyChanged
{
// Assume INotifyPropertyChanged implementation with this utility to raise the event
void RaisePropertyChanged(string property) { // ...blah blah blah ... }
}
// Interface for nameable object
public interface INameable
{
string Name { get; set; }
}
// View model for nameable object
public class NameableViewModel : BaseViewModel, INameable
{
private string _name;
public string Name
{
get => _name;
set
{
if (value == _name) return;
_name = value
RaisePropertyChanged();
}
}
// Main view model exposes named object by interface, NOT by view-model
public class MainViewModel : BaseViewModel
{
public INameable NameableObject { get; set; }
}
Here's a view binding to INameable
instead of NameableViewModel
<UserControl x:Class="MyView"
(... blah blah blah... namespace declarations...)
d:DataContext="{d:DesignInstance MainViewModel}">
<TextBox DataContext={Binding NameableObject.Name, Mode=TwoWay}"/>
</UserControl>
This works fine in WPF because it queries any data context for INotifyPropertyChanged
. It receives the PropertyChanged notifications even though all it got was INameable
. But if I forget to set up my classes right, WPF will just silently never get property changed notifications. I might end up having errors that take a while to notice or track (testing resources are limited here).
Furthermore, in my code-behind, I sometimes manually monitor some objects via INotifyPropertyChanged
using Josh Smith's excellent PropertyObserver
.
public class PropertyObserver<TPropertySource>
: IWeakEventListener
where TPropertySource : INotifyPropertyChanged
{
... blah blah blah..
}
This does require INotifyPropertyChanged at build time, and that was great when I was using instances of my BaseViewModel. But now that I merely have an interface, I must query it myself and rely on a run-time error to let me know I've screwed up.
Which leads me to my questions. One general and one very specific:
NotSupportedException
? Something else?Upvotes: 0
Views: 1076
Reputation: 2497
I'm not entirely sure what the "design" or "practice" that you refer to is. I don't see a general pattern, only a specific use of an interface, for which its purpose is not clear to me.
In my experience, it's best to keep the view models as simple as possible. In some cases, they don't even need to implement INotifyPropertyChanged
(think of a read-only view model). Generally, I use an MVVM framework (such as MVVM Light Toolkit) that provides a ViewModelBase
. Almost every view model I make derives from ViewModelBase
, and the view model simply contains setters, getters, and commands.
For your second question, I think the specific exception depends on the intent for the use of the interface. But perhaps a general exception could be InvalidOperationException
.
Upvotes: 1