3

We have a custom panel class that animates its children via an internal DoubleAnimation object. However, we want to expose the animation's Duration dependency property as a public property of our panel so the user can change it in their XAML when using our panel. But we don't want to expose any other part of the animation object, just the duration.

The first thing that keeps getting suggested to me is to use the PropertyChanged notification, but that would only work for the setter, not the getter. We also can't simply create a .NET property since XAML bypasses the .NET property altogether.

A co-worker of mine had a clever idea... use two-way data binding between the outer property and the internal object's property, which actually seems like a pretty neat solution. However, data binding aside, is there another/a better way to do this... exposing an internal object's dependency property via it's containing object's public interface?

Updated:

Looks like two-way DataBinding was the way to go. (Thanks @Jeff!) To that end, here's what I found to be the best way to set up the outer DP so it's a perfect match--metadata, defaults and all--for the inner object's DP! Then use Jeff's binding trick and you're done!

public Duration Duration {
    get { return (Duration)GetValue(DurationProperty); }
    set { SetValue(DurationProperty, value); }
}

public static readonly DependencyProperty DurationProperty = DoubleAnimation.DurationProperty.AddOwner(
    typeof(SlideContentPanel));
Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286
  • 1
    Another way to look at this is how do you use an internal object as the backing storage for the containing objects d-prop(s). Although I already accepted the 'binding' answer below, that technically still stores the value twice: once on the containing object then again on the internal object, then the binding keeps them in sync. I'm wondering how you can just delegate a d-prop down to an internal object so it's only stored in the internal object and thus doesn't need to use bindings in the first place (if this is even possible.) – Mark A. Donohoe Oct 08 '10 at 21:45
  • have you ever found the way to avoid duplicated values and binding? – Piotr Golacki Aug 18 '22 at 09:51

2 Answers2

5

Try this... Create equivilant dependency properties on the outside objects, then bind from the inside object to the outside object. This will work in both directions.

Binding durationBinding = new Binding(){
    Source = _doubleAnimation,
    Path   = new PropertyPath("Duration"),
    Mode   = BindingMode.TwoWay
};
BindingOperations.SetBinding(this, SlideContentPanel.DurationProperty, durationBinding);

For the xaml lovers

<UserControl x:Class=”Controls.DataGrid.DataGrid2"
Name="rootControl">

<Grid>       
    <xcdg:DataGridControl Grid.Row="0"
       Name="internalDataGrid" 
       SelectedItem="{Binding ElementName=rootControl, Path=SelectedItem}"
       EditTriggers="{Binding ElementName=rootControl, Path=EditTriggers}"
 />
jeff
  • 3,269
  • 3
  • 28
  • 45
0

Something strikes me as odd about your "problem", so here are some thoughts that may clear things up.

A dependency property can be both read and set by your code. Why not just use that instead of this internal storage?

If you want to use the internal storage value for performance reasons, use the property changed notification that you already said would work. When the property changes, update your internal value. When YOU change the property internally, call the dependency property setter at appropriate intervals to update everyone else (ignoring the property change event you would receive from that).

Maybe your situation requires something other than this, but the second option ought to be as complicated as something like this should get.

John Fisher
  • 22,355
  • 2
  • 39
  • 64
  • As you stated above, property changed only handles the setter, thus making *you* responsible in keeping the two in sync if you change the value on the internal object. That's a lot of extra work if there are a lot of touch-points where it can be changed. As for your comment of using a d-prop instead of the internal object I think you've missed the point. That internal object is what makes this panel work! Look at it another way... all we're trying to do is expose a property of that internal animation object so a user may customize that value in XAML. Make sense? – Mark A. Donohoe Oct 08 '10 at 21:20
  • It sounds like you went with a variation of the first option. I'm glad you figured out how to do that simply. – John Fisher Oct 09 '10 at 00:02