HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Managing inherited dependency properties in WPF

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
managinginheritedpropertieswpfdependency

Problem

Exposing Inherited Members

I have a WPF Custom Control library (ContentToggleButton) and an app (spec) to test it. The Custom Controls, which derive from Presentation Framework elements, expose inherited properties as well as new properties to the consumer.

This means that the consuming app depends on the Framework Elements as well as the Custom Controls as shown by the four dependencies from the top and bottom of MainWindow in the following diagram.

Reimplementing Inherited Members

The references were due to the IsChecked dependency property of the ToggleButton base class of the ContentToggle object and the Click event of the ButtonBase base class of the ButtonContent object. The former was bound in the XAML to a method on the MainWindow class in the View, code behind.





The RelativeSource resource is defined in Resource Dictionary in App.xaml.





The second dependency was due to subscribing to the Click event inherited from ButtonBase in the MainWindow class.

Plain.Click += (s, e) => {
Toggle.IsEnabled = !Toggle.IsEnabled;
};


By adding a custom DP called InitialState on ContentToggle and binding to that instead then using it to initialise IsChecked in the Loaded event, one of the dependencies was eliminated.

public static readonly DependencyProperty
InitialStateProperty = DependencyProperty.Register(
"InitialState", typeof(bool?), typeof(ContentToggle),
new PropertyMetadata(false));

public bool? InitialState
{
get { return (bool?) GetValue(InitialStateProperty); }
set { SetValue(InitialStateProperty, value); }
}


The second dependency was eliminated by reimplementing the Click event in the custom property and routing the original event through it.

`public static readonly RoutedEvent ClickEvent = EventManager.RegisterRoutedEvent(
"Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ContentToggle));

public new event RoutedEventHandler Click
{
add { AddHan

Solution

Well, this looks like a really bad idea.

  • To begin with... what's the point? I mean what is so bad about having a dependency on standard .Net assembly? It is already installed on the machine as part of .Net installation, so this dependency does not affect the size of your app. Am I missing something?



  • This design works under fairly naive assumption, that the app will not change in any way as the time goes on. And it might be the case for your particular app, but it is not the case in general. Imagine I am using your library, and I want to subscribe to ContentToggle.Loaded event. What should I do? Should I call you at 3AM and ask you to also override this event with new keyword? Will you do the same thing for every single event (or property) found on FrameworkElement? Will you then test every single interaction, to make sure you did not break standard behavior? If you are not willing to take this all the way - don't do it at all.



  • I don't even want to begin imagining all the potential pitfalls. What will happen if someone sets e.Handled = true; for your new Click event? Will your base event keep going? What will happen, if I have a style for regular button that uses `` and I want to override this setter for your button's style? How is it going to work, will I have two event handlers as a result or just one? Etc, etc.

Context

StackExchange Code Review Q#148571, answer score: 2

Revisions (0)

No revisions yet.