About Hasmukh patel

My Photo
Harrow, London, United Kingdom
Dot-Net developer with expertise in Web, WPF, Win-form applications. Have worked on Asp.net,mvc , WPF and Win-forms projects in c#.net language having Sql-Server/Oracle as database with service oriented architecture using test driven development. Having complete knowledge of SDLC and have successfully worked and implemented it on projects.

Dependency Properties & Attached Properties


Dependency Properties & Attached properties

Dependency Properties looks similar to normal CLR properties but its more complex and more powerful feature of XAML.
The main difference is, that the normal CLR properties are backed a private variable of your class, whereas the Dependency Properties are backed by DependencyObject’s GetValue and SetValue which resolved value dynamically by calling these two methods.

Getter and setter value mechanism

XML processor resolves the value by the precedence from high to low.

GetValue()
SetValue()
1
Animation

2
Binding Expression

3
Local Value
Local Value
4
Custom Style trigger

5
Custom template trigger

6
Custom Style Setter

7
Default Style Trigger

8
Default Style Setter

9
Inherited Value

10
Default Value


The Advantage of dependency properties

·         Reduce memory footprint:  most of the UI element have a no value just it use the default value.
·         Value inheritance: if there is no value defined then inherit from parents.
·         Change notification: built-in mechanism which binding get notification by registering of property metadata, when the value of the property has been changed.
Example of a Dependency property
To create a Dependency property, add a static type of DependencyProperty and call Register static method of DependencyProperty class to create instance of a dependency property. To create a property of your class, create normal CLR property and replace with GetValue() and SetValue()  instead of private variable like a wrapper  property.
Note : Do not write any logic in getter and setter of the dependency property, because getter might not call some time as explain in above table and setter might not call by XML but it may call SetValue() directly instead of your setter.

public
static readonly DependencyProperty TempratureProperty =
     DependencyProperty.Register( " Temprature", typeof(int),
     typeof(MyClockControl), new FrameworkPropertyMetadata(0));

// .NET Property wrapper
public int Temprature
{
    get { return (int)GetValue(TempratureProperty); }
    set { SetValue(TempratureProperty, value); }
}
Each dependency property provides  Callbacks for value change notification, value coercion and value validation. These callbacks  can be registered with FrameworkPropertyMetadata  object of the dependency property.
public static readonly DependencyProperty TempratureProperty =
     DependencyProperty.Register( " Temprature", typeof(int),
     typeof(MyClockControl),
     new FrameworkPropertyMetadata(0,
                       OnTempraturePropertyChanged, 
                       OnCoerceTempratureProperty),
     OnValidateTempratureProperty);

// .NET Property wrapper
[Bindable(true)]
public int Temprature
{
    get { return (int)GetValue(TempratureProperty); }
    set { SetValue(TempratureProperty, value); }
}
Value Change Callback
private static void OnTempraturePropertyChanged(DependencyObject source, 
        DependencyPropertyChangedEventArgs e)
{
    var control = source as MyTempratureControl;
    var temprature = (int)e.NewValue;
    // write your logic here...
}
Coerce Value Callback
private static object OnCoerceTempratureProperty( DependencyObject sender, object data )
{
    if ((int)data > MaxTemprature )
    {
        data = MaxTemprature;
    } else if ((int)data < MinTemprature )
    {
        data = MinTemprature;
    }
 
    return data;
}
Validation Callback
private static bool OnValidateTempratureProperty(object data)
{
    // write your logic here...
    return (int)data>0 && (int)data <100;
}
 

Readonly DependencyProprites

Some dependency properties of UI controls are read only. They are often used to report state of a control, like IsMouseOver property. We can use normal CLR property but  Instead on normal CLR property, we might need trigger to get notification.
private static readonly DependencyPropertyKey IsHotPropertyKey = 
      DependencyProperty.RegisterReadOnly("IsHot", 
      typeof(bool), typeof(MyClass), 
      new FrameworkPropertyMetadata(false));
 
// Register the public property to get the value
public static readonly DependencyProperty IsHotProperty = 
      IsHotPropertyKey.DependencyProperty;    
 
// .NET Property wrapper
public int IsHot
{
   get { return (bool)GetValue(IsHotProperty); }
   private set { SetValue(IsHotPropertyKey, value); }
}

Attached Properties

Attached properties are a special kind of properties. They allow you to attach a value to an object that object doesn’t know anything about this value.
<Grid>
<!—Row s &columns definitions -->
    <Button Grid.Row="0" Grid.Column="0" Content="Click me!"/>
</Grid>
See ClickCommnad in the following example which on click execute a command from viewModel
<ListView x:Name="demoListView" >
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="Extensions:ListViewItemBehavior.ClickCommand" Value="{Binding ElementName=demoListView, Path=DataContext.ClickCommand}" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListViewItem">
                        <Border>
                            <GridViewRowPresenter Columns="{TemplateBinding GridView.ColumnCollection}" Content="{TemplateBinding Content}" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

public static class ListViewItemBehavior
{
    public static readonly DependencyProperty ClickCommandProperty =
        DependencyProperty.RegisterAttached(
        "ClickCommand",
        typeof(ICommand),
        typeof(ListViewItemBehavior),
        new FrameworkPropertyMetadata(null, ClickCommandChanged));
 
    public static ICommand GetClickCommand(ListViewItem listViewItem)
    {
        return (ICommand)listViewItem.GetValue(ClickCommandProperty);
    }
 
    public static void SetClickCommand(
        ListViewItem listViewItem, ICommand value)
    {
        listViewItem.SetValue(ClickCommandProperty, value);
    }
 
    static void ClickCommandChanged(
        DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        var item = depObj as ListViewItem;
        if (item == null)
            return;
 
        if (e.NewValue is ICommand)
        {
            item.PreviewMouseDown += OnListViewItemMouseDown;
        }
        else
        {
            item.PreviewMouseDown -= OnListViewItemMouseDown;
        }
    }
 
    static void OnListViewItemMouseDown(object sender, RoutedEventArgs e)
    {
        var item = sender as ListViewItem;
 
        if (item == null)
            return;
 
        var command = GetClickCommand(item);
 
        if (command.CanExecute(item.Content))
            command.Execute(item.Content);
    }
 
}

Clear Local Value

Assign null to dependency property is not really clearing the Locale Value of dependency property because null is also valid local value, there is static object  DependencyProperty.UnsetValue that describe as an unset value. Dependency property’s local value can be clear by invoking listView.ClearValue(ListView.ItemsSourceProperty) method.

No comments :