Ed Noepel

Lets say I'm making a cake and have a Bowl object (hiding IP is so much fun). In this bowl I put some ingredients, including sugar.

Code Block

public static readonly DependencyProperty SugarProperty =
DependencyProperty.RegisterAttached( "Sugar", typeof(_Sugars), typeof(Bowl),
new FrameworkPropertyMetadata(_Sugars.SugarsNoSugar,
FrameworkPropertyMetadataOptions.Inherits,
new PropertyChangedCallback(OnSugarChanged)) );


I then need to mix the ingredients, so I put a hand mixer into the bowl. To determine the mixer speed, the mixer needs to know some details about the sugar (confectionary sugar requires a lower speed than granulated). The bowl already gets notification when the Sugar property is changed, through the callback attached in the DP's definition. The mixer can determine the sugar type on request, because it can call Get/SetValue(Bowl.SugarProperty).

But my mixer object still needs to attach a handler to Bowl.SugarProperty's DependencyPropertyChanged event, lest someone pours powdered sugar in while mixing. I saw a few methods exposed in the DP, such as AddOwner, and OverrideMetaData, but neither seem to offer what I need. How can I handle this


Re: Windows Presentation Foundation (WPF) Handling a DependencyPropertyChanged callback from a child of the element to which the DP is attached

Drew Marsh

Implement INotifyPropertyChanged on the Bowl and make sure to raise the PropertyChanged event anytime the OnSugarChanged callback method is invoked. When your mixer starts up, it reads the initial value from the property and attaches to PropertyChanged for further updates while mid-mix.

HTH,
Drew





Re: Windows Presentation Foundation (WPF) Handling a DependencyPropertyChanged callback from a child of the element to which the DP is attached

Ed Noepel

So from my Mixer class, should I expose a property of type INotifyPropertyChanged, and set this property when the Bowl creates a Mixer object Or is there a more elegant way of attaching to the new PropertyChanged event on the Bowl




Re: Windows Presentation Foundation (WPF) Handling a DependencyPropertyChanged callback from a child of the element to which the DP is attached

Drew Marsh

No need for a property, it's just standard .NET event registration pattern. Your bowl exposes an event (INotifyPropertyChanged:: PropertyChanged) and your mixer just needs to attach to the event when it starts to "mix" the bowl. Might look something like this

Code Block

public class Mixer
{

public MixIt(Bowl bowl)
{

// Start listening for changes to the bowl

bowl.PropertyChanged += this.BowlPropertyChanged;

// logic here

// Stop listening for changes to the bowl

bowl.PropertyChanged -= this.BowlPropertyChanged;

}

private void BowlPropertyChanged(object sender, PropertyChangedEventArgs args)

{

switch(args.PropertyName)

{

case "Sugar":

// respond to change however u like

break;

}

}

}

HTH,

Drew





Re: Windows Presentation Foundation (WPF) Handling a DependencyPropertyChanged callback from a child of the element to which the DP is attached

Dr. WPF

Oh, soooo many sweet options! I'd do the following.

Put a binding on some property of your Mixer to the Sugar property on the bowl. The following should work since you have an inherited attached DP:

Code Block

<sn:Mixer Tag="{Binding Path=(sn:Bowl.Sugar),

RelativeSource={RelativeSource Self}}" />

Use the property changed handler for the DP to determine when the change occurs.

Code Block

TagProperty.OverrideMetadata(typeof(Mixer),

new PropertyChangedCallback(OnTagChanged));

P.S. We need more questions like this.






Re: Windows Presentation Foundation (WPF) Handling a DependencyPropertyChanged callback from a child of the element to which the DP is attached

Ed Noepel

Mr. Marsh:
The purpose of adding a property would be so that the Mixer has a reference to the Bowl. Right now, the Mixer doesn't know anything about the container; you could mix in a bowl or a bathtub. The bowl happened to be a special case where sugar is involved (one would never put sugar in the bathtub), hence why I chose to attach to it rather than some superclass.

Dr. WPF:
As I hinted in last paragraph of my first post, DependencyProperty.OverrideMetadata doesn't provide any overload that allows me to define a new PropertyChangedCallback. If it did, this would all just be really easy. Is it supposed to

Your assistance is greatly appreciated.




Re: Windows Presentation Foundation (WPF) Handling a DependencyPropertyChanged callback from a child of the element to which the DP is attached

Dr. WPF

Umm... my example used a binding on the Tag property. This is registered as a framework property... it uses FrameworkPropertyMetadata.

Here's the code you need:

Code Block

static Mixer()

{

TagProperty.OverrideMetadata(typeof(Mixer),

new FrameworkPropertyMetadata(

new PropertyChangedCallback(OnTagChanged)));

}

private static void OnTagChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

{

Mixer mixer = d as Mixer;

// your code goes here

}

If for some reason you don't have any framework properties to which to bind the Sugar property, just define your own DP.




Re: Windows Presentation Foundation (WPF) Handling a DependencyPropertyChanged callback from a child of the element to which the DP is attached

Dr. WPF

You don't really need a binding at all if you want to simply override the metadata for Bowl.SugarProperty in the Mixer class.

Assume you have markup something like the following:

Code Block

<Grid>

<src:Bowl Sugar="Granulated">

<Grid>

<src:Mixer />

</Grid>

</src:Bowl>

</Grid>

Assume that the Sugar property is defined within the Bowl class like this:

Code Block

public static readonly DependencyProperty SugarProperty

= DependencyProperty.RegisterAttached("Sugar",

typeof(_Sugars), typeof(Bowl),

new FrameworkPropertyMetadata(_Sugars.SugarsNoSugar,

FrameworkPropertyMetadataOptions.Inherits));

You can add a property changed callback in the mixer for the inherited Sugar property as follows:

Code Block

static Mixer()

{

Bowl.SugarProperty.OverrideMetadata(typeof(Mixer),

new FrameworkPropertyMetadata(

new PropertyChangedCallback(OnSugarChanged)));

}

private static void OnSugarChanged(DependencyObject d,

DependencyPropertyChangedEventArgs e)

{

// add your code here

}

This should all work fine. If you have any trouble, let me know and I can put together a working sample.






Re: Windows Presentation Foundation (WPF) Handling a DependencyPropertyChanged callback from a child of the element to which the DP is attached

Ed Noepel

This was exactly what I was looking for...works great! Thank you.




Re: Windows Presentation Foundation (WPF) Handling a DependencyPropertyChanged callback from a child of the element to which the DP is attached

AlexTre

Hi

I think I am reading an amazing thread, I did learn something from it, I also have an question,

from reading below lines

TagProperty.OverrideMetadata(typeof(Mixer),

new FrameworkPropertyMetadata(

new PropertyChangedCallback(OnTagChanged)));

if I want to do something silimilar, for example,

ComboBox.IsMouseOverProperty.OverrideMetadata(..........)

but I dont think I can, because the ComboBox.IsMouseOverProperty' Metadata is readonly, Is there any way I can go around this






Re: Windows Presentation Foundation (WPF) Handling a DependencyPropertyChanged callback from a child of the element to which the DP is attached

Dr. WPF

Correct. When a dependency property is registered as read-only, you get back a DependencyPropertyKey object. This key is required if you want to override the property's metadata. Most classes make the key private. Some classes will make it protected so that derived classes can override metadata, although this is rarely necessary for framework classes because they tend to provide protected methods for things like OnIsMouseOverChanged.

You certainly won't be able to override the metadata for ComboBox.IsMouseOverChanged from an unrelated (non-descendant) class, unless of course, you want to use reflection. Then all things are possible Smile (except running in partial trust).