What are the scenarios in which we need to use dependency property in WPF? - wpf

We can achieve the binding by simply CLR property, so why do we need to use DP?

When do you need DPs over CLRPs?
When you need binding
when you need property value change callback (Default Implementation)
When you need property value validation
When you need animation
When you need property value inheritance
When you need to attach a property value to another element (Attached Property, but still)
When you need styling
Some of these can be implemented in CLR properties. But, with DPs, its piece of cake.

Typically these are declared in UserControls and derived controls.
You can bind to a CLR property, but you can't bind with a CLR property; you'll need a dependency property to do any binding.
Edit (in response to comment)
Let's say you need a TextBox, but you want to customize it to have different behaviour in "EditMode" and "ReadMode". You'll need to either create a derived class or a UserControl; in either case you'll add a DependencyPropery.
public class TextBoxWithModes : TextBox
{
public bool EditMode
{
get { return (bool) GetValue(EditModeProperty); }
set { SetValue(EditModeProperty, value); }
}
public static readonly DependencyProperty EditModeProperty = DependencyProperty.Register(
"EditMode", typeof (bool), typeof (TextBoxWithModes));
}
With this in place, you can declare it in XAML:
<Namespace:TextBoxWithModes Text="enter text here"
Width="200"
HorizontalAlignment="Center"
EditMode="{Binding IsChecked, ElementName=editModeCheckBox}" />

Related

About DependencyProperty in WPF

I'm very new to WPF and while studying (particularly creating a user control), I stumbled upon this thing called "DependencyProperty".
I understand how it works in code but why and when do we need it when I can just create a property and expose it for public use.
Example:
XAML:
<UserControl.....>
<StackPanel Orientation="Vertical">
<TextBlock x:Name="label" Text="Hello"/>
<TextBlock x:Name="text" Text="World!" />
</StackPanel>
</UserControl>
CS file:
public partial SampleUserCtrl : UserControl
{
public string LabelText { get { return this.label.Text; } set { this.label.Text = value; } }
public string TextBoxText { get { return this.text.Text; } set { this.text.Text = value; } }
}
DependecyProperty in WPF has different uses.
Advantages compared to normal .NET property
Reduced memory footprint It's a huge dissipation to store a field for
each property when you think that over 90% of the properties of a UI
control typically stay at its initial values. Dependency properties
solve these problems by only store modified properties in the
instance. The default values are stored once within the dependency
property.
Value inheritance When you access a dependency property the value is
resolved by using a value resolution strategy. If no local value is
set, the dependency property navigates up the logical tree until it
finds a value. When you set the FontSize on the root element it
applies to all textblocks below except you override the value.
Change notification Dependency properties have a built-in change
notification mechanism. By registering a callback in the property
metadata you get notified, when the value of the property has been
changed. This is also used by the databinding.
As you dig deeper to WPF you will also stumble upon DataBinding and object-oriented design patterns like MVVM or MVPVM. Both patterns rely on DataBinding which is achieved through using of Dependency Properties. You cannot perform data binding if it is not a dependency property.
Basically data binding through dependency properties allow the user to update the view when updating a value through code.
Ex: In Windows Forms in order to update a label text you assign its value on the code behind like this:
lbl1.Text = "foo";
In data binding where as you bind in the XAML (View)
<label Text = "{Binding foo}"></label>
and update the values in your code behind:
foo = "foo";
I am not an expert myself so sorry if I might sound confusing.
Dependency property has many benefits over normal property.
A dependency property value can be set by referencing a resource
It can reference a value through data binding
It can be animated. When an animation is
applied and is running, the animated value operates at a higher
precedence than any value (such as a local value) that the property
otherwise has.
You can learn more about it from msdn.
The main advantage of DP property you can find anything in DP like your Control info and you current DataContext info.
public string MyProperty
{
get { return (string)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(string), typeof(MyUserControl), new PropertyMetadata(null, (s, e) => OnChangedValue(s, e)));
private static void OnChangedValue(DependencyObject s, DependencyPropertyChangedEventArgs e)
{
throw new NotImplementedException();
}

WPF - What's the interest of dependency property without callback

I don't understand the interest of a dependency property without callback defined.
A callback is just an added convenience -- dependency properties are integrated into the framework runtime, and have a built-in callback mechanism that updates any bindings. That is, if you set a binding with a dependency property as the source, then the target will update automatically when the dependency property changes.
For example, let's say you have a custom control with a DP defined:
public string SomeDP
{
get { return (string)GetValue(SomeDPProperty); }
set { SetValue(SomeDPProperty, value); }
}
public static readonly DependencyProperty SomeDPProperty =
DependencyProperty.Register("SomeDP", typeof(string), typeof(SomeFrameworkElement), new PropertyMetadata(null));
And if you set up a binding with the DP as the source for a TextBlock's "Text" property:
<local:SomeFrameworkElement x:Name="someFrameworkElement" SomeDP="initial" />
<TextBlock Text="{Binding ElementName=someFrameworkElement,Path=SomeDP}" />
Then whenever "someFrameworkElement"'s "SomeDP" property changes, the text will also change.

Why does my UI not update to reflect the data I have bound to it?

I've bound the visibility of some buttons to a bool, but when the bool changes, the button's visibility does not change. Why could this be?
The boolean is set up as such:
public static readonly DependencyProperty editModeToggle = DependencyProperty.Register("editMode", typeof(bool), typeof(Window));
public bool EditMode
{
get { return(bool)GetValue(editModeToggle); }
set { SetValue(editModeToggle, value); }
}
I'm pretty sure the binding isn't at fault.
[Note: I have set up a Converter that works and the binding works. The visibility just doesn't change when I change from true to false or vice versa]
Binding:
<Button Content="Test" Visibility="{Binding ElementName=mainWindow, Path=EditMode, Converter={StaticResource BooltoVisibilityConverter}/>
There are a few things you need to check when a binding does not work as expected:
Does the bool property notify change using
INotifyPropertyChanged?
Do you use a converter to convert from
bool to Visibility?
Do you see any binding errors in output
window?
Have you tried putting a breakpoint on binding in xaml
or setter in bool property?
As you have mentioned in your comment, you have not implemented INotifyPropertyChanged interface.
The need to implement the interface is whenever value of the property in ViewModel changes, there has be be a way for binding to know that. So, after implementing INotifyPropertyChanged, for each property, you raise the PropertyChanged event with the property name in it. That way, the binding knows that value of the property has changed.
There are lots of articles online. Here is one to get you started: INotifyPropertyChanged and WPF
Dependency Property registration is not correct -
public static readonly DependencyProperty editModeToggle =
DependencyProperty.Register("editMode", typeof(bool), typeof(Window));
It should be-
public static readonly DependencyProperty editModeToggle =
DependencyProperty.Register("EditMode", typeof(bool), typeof(Window));
Notice the spelling of property - 'E' should be capital since its case sensitive and your property name is EditMode not editMode.
In this case you don't need point 1 from decyclone list since you are using a dependency property. I think that you should add Mode=TwoWay in binding if you don't have it, that will solve it.

How can I bind from a user control to an external object in XAML?

I have an image inside a user control that I want to bind it's visibility to a property I have set up in a class object. The dependency properties are set up and working correctly, but I don't know how to set the binding properly on the image.
The user control and class object are in the same namespace. I thought I would need to set the ElementName to the window or the RelativeSource to the class object, but I'm not getting it to work out.
Here's what a dependency property looks like (defined in MigrateUserWizardObject.cs, this inherits from DependencyObject, this resides in the UserAccountMigrator namespace):
public static readonly DependencyProperty DatabaseStepCompletedVisibilityProperty = DependencyProperty.Register("DatabaseStepCompletedVisibility", typeof(Visibility), typeof(MigrateUserWizardObject));
public Visibility DatabaseStepCompletedVisibility
{
get
{
return (Visibility)GetValue(DatabaseStepCompletedVisibilityProperty);
}
set
{
SetValue(DatabaseStepCompletedVisibilityProperty, value);
}
}
Here's an image that I want bound to this dependency property (defined in ProgressUserControl.xaml, this inherits from UserControl, this resides in the UserAccountMigrator namespace as well):
<Image x:Name="DatabaseCompleted" Source="{StaticResource GreenCheckMarkSource}" Visibility="{Binding Path=DatabaseStepCompletedVisibility, UpdateSourceTrigger=PropertyChanged}" Height="20" HorizontalAlignment="Right"></Image>
This is due to the fact that the DataContext of the image is the user control. How can I make this work?
I think you should look into using the Model-View-ViewModel pattern. Instead of setting the DataContext to the UserControl, set it to an instance of another class (ProgressViewModel, for example). This view model would have all the properties you want to bind to (including your DatabaseStepCompletedVisibility property) and makes it much easier. Right now you are wanting to bind some things to the UserControl, some things to another object somewhere else, etc.. and, as you have found, makes it difficult. Here is more information:
http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/432/MVVM-for-Tarded-Folks-Like-Me-or-MVVM-and-What-it-Means-to-Me.aspx
Without going that approach, you have to have an instance MigrateUserWizardObject to bind to. You can put that instance in your UserControl (if you insist on using it as the DataContext), then you can bind the the property of the MigrateUserWizardObject property of the UserControl. Also, your MigrateUserWizardObject doesn't have to be a dependency object or dependency property to bind to. A better pattern would be to make it a plain c# class that implements the INotifyPropertyChanged interface.

Custom Dependency Properties and TwoWay binding in WPF

We have an object that derives from DependencyObject, and implements some DependencyProperties.
Basically something like this:
class Context : DependencyObject {
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register ("Name", typeof (string), typeof (Context), new PropertyMetadata (""));
public string Name {
get {
return (string)this.GetValue (NameProperty);
}
set {
this.SetValue (NameProperty, value);
}
}
}
This works, the property is setup, can be bound, etc. The issue comes when I bind TO the propery from WPF, using a TwoWay bind. The TwoWay part never actually happens, WPF never calls the set of this property. I have set my binding up like this:
<TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
In this case, typing in the text box should immediately update the Name property, but it does not. If I change the Name property to be a regular POCO property, it works (though the other side of the TwoWay obviously doesn't unless I implement INotifyPropertyChanged).
What am I doing wrong here? This should be a really simple thing to do, but it's causing me no end of headaches.
This is expected behavior. The CLR property is merely a wrapper around the underlying DependencyProperty. WPF often optimizes by calling GetValue and SetValue directly. If you need custom logic to execute then use the metadata of the DependencyProperty.
After this issue cost me some time:
For those of you who have the same problem, but - like me - don't see the solution in the answer above:
To support inheritance of the DataContext, the custom class (Context in this case) has to be derived from FrameworkElement rather than DependencyObject. That's all.
Marc

Resources