WPF Databinding, INotifyPropertyChanged, and Dependency Properties

XAML isn't required (or allowed!) This means that there is no need to databind properties from a CLR object, or an object that implements INotifyPropertyChanged, or an object with DependencyProperties. Instead, you just wire in data manually at the time of creating your Framework Elements in BeginComposite . . . EndComposite. Then, at the time of persisting data, you retrieve directly and manually as well likely using GetChildFromParent or GetChildFromComposite to get a handle to each Child.

But what about scenarios where you would like to leverage the WPF Databinding engine merely to make the color of one Framework Element dependent on another, even if the Brush property changes at runtime? You could always leverage WPF-CPS Dependency Events, wiring up an Observable to a DependencyPropertyChanged event. Yet, it may be simpler to just leverage WPF Databinding.

To do so, I added several methods that may wire dependencies between properties on Parents, Children, Composites (Borders), and Containers. Most of these are wiring up one Framework Element's property to another's.

However, there are also a few special purpose methods such as wiring up to a Dependency Object, wiring up via a Style, or wiring up via a Trigger.

How to DataBind One Child's Property to Another Framework Element's Property

This is the standard usage. This will make myLabel's Background color dependent on the Tab Label's Background color property. If you change the Tab Label's Background color at run-time, then myLabel's color will change too. This method accomplishes this via a standard Binding and PropertyPath. This method also contains an overload which supports passing in a ValueConverter.

FrameworkElement myTabLabel = this.SelectAllFrameworkElementsByClass("tabLabel", false).First();

myLabel.DataBindOneChildsPropertyToFE<Label, Label>(myTabLabel, Border.BackgroundProperty, Label.BackgroundProperty, System.Windows.Data.UpdateSourceTrigger.PropertyChanged, System.Windows.Data.BindingMode.OneWay);



How to DataBind One Child's Property to Another Framework Element's Property in BeginComposite

This is the standard usage as well. This will get the Label at row-column 3-0 and make its Background color dependent on a TextBox's Background color property. The TextBox is retrieved at column 2-0. If you change the TextBox's Background color at run-time, then the Label's color will change too. This method accomplishes this via a standard Binding and PropertyPath.

Border myComposite = ccl3d.BeginComposite<ContentControl3D>(gridguid1)
                 .AddLabel<ContentControl3D>(0, 0, "Front Side: Click Here to Rotate", Brushes.Transparent)
                   .AddLabelSettingBackgroundViaStyle<ContentControl3D>(1, 0, "Children:", reuseBrush)
                   .AddAnything<TextBox, ContentControl3D>(2, 0)
                  .DataBindOneChildsPropertyToAnother<Label, TextBox, ContentControl3D>(3, 0, 2, 0, Label.ContentProperty, TextBox.TextProperty, System.Windows.Data.UpdateSourceTrigger.PropertyChanged, System.Windows.Data.BindingMode.OneWay)                
                   .EndComposite(new ContentControl3DArgs(ContentControlEnum.Front));



How to DataBind One Child's Property to a Custom Dependency Object's Property

This is a more advanced usage scenario. This will make myLabel's Background color dependent on the Custom Dependency Object BrushTest's BrushProperty color. If you change the BrushProperty color at run-time, then myLabel's color will change too.

public class BrushTest : DependencyObject
{
        public Brush BrushProperty
        {
            get { return (Brush)GetValue(BrushPropertyProperty); }
            set { SetValue(BrushPropertyProperty, value); }
        }

// Using a DependencyProperty as the backing store for BrushProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BrushPropertyProperty =
            DependencyProperty.Register("BrushProperty", typeof(Brush), typeof(BrushTest), new PropertyMetadata(Brushes.White));
}

BrushTest brTest = new BrushTest();
brTest.BrushProperty = Brushes.Orange;

Label myLabel = cb1.GetChildFromParent<Label, ComboBox>(cbGuid4, 1, 0);
myLabel.DataBindOneChildsPropertyToDepObj<Label>(brTest, Label.BackgroundProperty, BrushTest.BrushPropertyProperty, System.Windows.Data.UpdateSourceTrigger.PropertyChanged, System.Windows.Data.BindingMode.OneWay);

brTest.BrushProperty = Brushes.Pink;



How to DataBind One Child's Property to Another Via a Trigger

The static class TriggerDataBinding contains a DataBindOneChildsPropertyToFEViaTrigger method that allows databinding one element's property to another framework element's property whenever a trigger is satisfied. In the example below, myLabel's background property is bound to someOtherLabel's background property such that when the mouse is over myLabel (IsMouseOverProperty is true on myLabel) then the binding will occur. For instance, myLabel's background may be set as blue, but when the mouse is over myLabel it will change to whatever color background someOtherLabel is set to, let's say orange.

Label myLabel = myComposite.GetChildFromComposite<Label, ContentControl3D>(10, 0);

myLabel.DataBindOneChildsPropertyToFEViaTrigger<Label, Label>(someOtherLabel, Border.BackgroundProperty, Label.BackgroundProperty, System.Windows.Data.UpdateSourceTrigger.PropertyChanged, System.Windows.Data.BindingMode.OneWay, FrameworkElement.IsMouseOverProperty, true);


How to DataBind One Child's Property to Another Via a Style

This example will make myLabel's Background color dependent on the Tab Label's Background color property. If you change the Tab Label's Background color at run-time, then myLabel's color will change too. This method accomplishes this internally via a Style which may be important in certain cases where the WPF order of precedence in applying property values at runtime may matter. See details on order of precedence here: http://msdn.microsoft.com/en-us/library/ms743230(v=vs.110).aspx

FrameworkElement myTabLabel = this.SelectAllFrameworkElementsByClass("tabLabel", false).First();

myLabel.DataBindOneChildsPropertyToFEViaStyle<Label, Label>(myTabLabel, Border.BackgroundProperty, Label.BackgroundProperty, System.Windows.Data.UpdateSourceTrigger.PropertyChanged, System.Windows.Data.BindingMode.OneWay);


How to DataBind One Child's Property to a Border's

As aforementioned, there are multiple method overloads to support not just Children, but Parents, Composites (Borders), and Containers too. Below are two examples, binding a Child's property to a Border's and vice versa, binding the Border's property to a Child's.

myBorder.DataBindOneChildsPropertyToBorders<TextBlock, ComboBox>(key1, 1, 0, TextBlock.BackgroundProperty, Border.BackgroundProperty, System.Windows.Data.UpdateSourceTrigger.PropertyChanged, System.Windows.Data.BindingMode.OneWay);

myBorder.DataBindBordersPropertyToOneChilds<TextBlock, ComboBox>(key2, 1, 0, Border.BackgroundProperty, TextBlock.BackgroundProperty, System.Windows.Data.UpdateSourceTrigger.PropertyChanged, System.Windows.Data.BindingMode.OneWay);

Last edited Mar 15, 2014 at 9:33 PM by stagathome0069, version 16

Comments

No comments yet.