I'm trying to bind to a WinForms control's DataSource property in my WPF application but I'm not having much luck...
Falafel.com gives it a shot, but although it claimes that a DependencyObject is not required to perform the binding, that seems to be the only way of doing it.
Has anyone done this before?
A. For objects not derived from DependencyObject, you don't have access to SetBinding() or ClearBinding() methods. Instead you may call the static methods BindingOperations.SetBinding() and BindingOperations.ClearBinding().
This is to actually bind a source and a target, and it can be done from any object using the static methods.
B. Now about the source and target involved in the binding, there are constraints that you can read here and that summarize to:
"The target of the binding can be any accessible property or element that is derived from DependencyProperty—an example is a TextBox control's Text property. The source of the binding can be any public property, including properties of other controls, common language runtime (CLR) objects, XAML elements, ADO.NET DataSets, XML Fragments, and so forth."
In turn DependencyProperty can exist (if I'm not wrong) only in a DependencyObject. So the target needs to live in a DependencyObject, but not the source, and not the object from where the binding is created.
And this is not exactly true, you can also use a target that is not a DO, look at the code in this page.
Also remember that you can perform a
reverse binding using
OneWayToSource type of binding. In
this case the target has not to be a
DependencyObject.
Related
I'm familiar with the concept that a collection used for a WPF Binding (for example, ItemsSource) actually uses the default collection view for that collection, but I am looking for some clarification on where that happens. Potentially depending on that answer, what is the recommended way to implement similar binding behavior if I am creating my own UserControl that has its own property like ItemsSource and I want to use ICollectionView functionality on it within my UserControl?
So if my UserControl has a ItemsSource property like:
public static readonly DependencyProperty TestPropProperty =
DependencyProperty.Register("TestProp", typeof(System.Collections.IEnumerable), typeof(MyUserControl),
new FrameworkPropertyMetadata(null, TestPropChanged, null));
And my XAML uses it like this:
<local:MyUserControl TestProp="{Binding MyCollection}"/>
Let's say MyCollection is of type ConfigCollection, my own type, derived from ObservableCollection. From MyUserControl's perspective, the binding sets TestProp to an object of type ConfigCollection (NOT a Collection View object).
The MS docs: https://learn.microsoft.com/en-us/dotnet/desktop/wpf/data/?view=netdesktop-6.0#binding-to-collections
Under "Using a default view", state:
WPF also creates a default collection view for every collection used as a binding source. If you bind directly to a collection, WPF binds to its default view.
That seems to be pretty universal, so in my case I was thinking it might be set as a Collection View whose source was MyCollection, but that is not the case.
So, does the "magic" of translating a collection into its default collection view all happen within each control's code? Is there a recommended way of making sure my ItemsSource can accept either a collection (and use the default view) or accept a Collection View and then use that specific view rather than the default?
When should I use dependency properties in WPF?
They are static, so we save a lot on memory, compared to using .NET properties.
Other gains of using dependency properties over .NET properties are:
1) no need to check thread access
2) prompt a containing element to be rendered
etc...
So it seems I should ALWAYS use dependency properties in my projects where I use WPF?
Maybe for some trivial properties of helper classes here and there I could
get away with .NET properties...
Dependency Property is a broad concept to explain which might take couple of pages to write. So just to answer your main question, Dependency property is used where
You know the property is going to be the binding target i.e you are creating a user control/custom control and want property that should be binding driven.
You want automatic property change notifications (coerse and validation also).
We want value inheritance in styles,themes, parent or default value.
There is not need to create the properties on Model or ViewModel layer as dependency properties most of the time as that is not going to help much on memory saving front as most of the properties we define in model/VM will have values per instance as they will be constantly changing. Resolving Dependency property value is a burden in itself so making property dependency unnecessarily is not advisable.
Thanks
The main reason to create DependencyProperty is when you write you own WPF control.
DependencyProperties can be used as binding source and target, and can be animated.
The properties of all framework's controls are implemented as DependencyProperty, that why you can make powerful data binding in XAML.
However in most situation, like in with the MVVM pattern, you don't need dependency properties, INotifyPropertyChanged is enough.
The main difference is, that the value of a normal .NET property is read directly from a private member in your class, whereas the value of a DependencyProperty is resolved dynamically when calling the GetValue() method that is inherited from DependencyObject.
When you set a value of a dependency property it is not stored in a field of your object, but in a dictionary of keys and values provided by the base class DependencyObject. The key of an entry is the name of the property and the value is the value you want to set.
The advantages of dependency properties are
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.
check the below url for more details about the magic behid it
dependency properties in WPF
CLR Property vs. Dependency Property
A CLR property reads directly from the private member of the class. The Get() and Set() methods of the class retrieve and store the values of the property.
Whereas when you set a value of a Dependency Property it is not stored in a field of your object, but in a dictionary of keys and values provided by the base class DependencyObject. The key of an entry is the name of the property and the value is the value you want to set.
Advantages of a Dependency Property
Less memory consumption
The Dependency Property stores the property only when it is altered or modified. Hence a huge amount of memory for fields are free.
Property value inheritance
It means that if no value is set for the property then it will return to the inheritance tree up to where it gets the value.
Change notification and Data Bindings
Whenever a property changes its value it provides notification in the Dependency Property using INotifyPropertyChange and also helps in data binding.
Participation in animation, styles and templates
A Dependency Property can animate, set styles using style setters and even provide templates for the control.
CallBacks
Whenever a property is changed you can have a callback invoked.
Resources
You can define a Resource for the definition of a Dependency Property in XAML.
Overriding Metadata
You can define certain behaviours of a Dependency Property using PropertyMetaData. Thus, overriding a metadata from a derived property will not require you to redefine or re-implement the entire property definition.
Perhaps you should take another look at the Dependency Properties Overview page at MSDN.
Personally, I would only ever create a DependencyProperty when I really need to. For the most part, I use normal CLR properties in data type and view model classes to bind to... this is absolutely fine, as long as I implement the INotifyPropertyChanged interface.
So for all of my usual data bindings, I use normal CLR properties. I only declare a Dependency Property in order to provide some added functionality in a UserControl.
Dependency properties are used when you want data binding in a UserControl, and is the standard method of data binding for the WPF Framework controls. DPs have slightly better binding performance, and everything is provided to you when inside a UserControl to implement them.
Otherwise, you typically use INotifyPropertyChanged for binding elsewhere, since it's easier to implement in stand-alone classes and has less overhead. As far as your original assumptions:
There is a local instance of your variable, you definitely do not save any overhead over a property since there is significant data binding logic built-in.
They must be accessed on the main thread.
The Silverlight/WPF DependencyProperty enables data binding and indicates when the property has changed in value, without implementing INotifyPropertyChanged. My question is on how does this work at the low level - how does DependencyProperty or DependencyObject perform this change notification when neither DependencyObject, DependencyProperty, nor DispatcherObject define any events. Would this have something to do with the DispatcherObject.Dispatcher property?
Dependency properties, or the DependencyObject class, do not natively
support INotifyPropertyChanged for purposes of producing notifications
of changes in DependencyObject source property value for data binding
operations.
This excellent clarification was taken word-for-word from:
http://msdn.microsoft.com/en-us/library/ms752914.aspx
http://msdn.microsoft.com/en-us/library/ms753358.aspx
Dependency properties are tightly integrated with the binding system internally. So instead of "notifying that the property changed", the code that sets the dependency property can call directly into the binding system and tell it to updated.
Similarly, things like inherited/attached properties can be updated on any descendant elements and/or the layout/measure/arrange can be updated. It can even tell any triggers (in Styles or ControlTemplates) to be reevaluated.
The Dispatcher isn't really related, but may be used during the process.
So in short, it's baked into WPF/Silverlight.
Well, when you register a DependencyProperty you provide a callback to be called when the value changes.
Here you have more details. I don't think anything else is public about the internals of WPF. I might be wrong.
I have been reading about dependency properties in several books but all have one thing in common, they just tell us how they are implemented( using static readonly DependencyProperty etc.) but does not tell the exact way they work from inside.
I mean they are implemented as static but still applies to all objects.
Second point of confusion is attached properties.
Is there any tutorial available that can explain all these concepts in an easy way?
My mental model of how dependency properties work:
Any DependencyObject class implements two special properties. One, a static property of the class, is a dictionary of DependencyProperty objects. Every instance of the class can look inside that dictionary to find metainformation about each DependencyProperty - the property's name, its type, any callbacks that have to be called when it's get and set, how it participates in property inheritance, and so on. When you register a dependency property, you're adding an entry to this dictionary.
The other property is an instance property: it's a dictionary, keyed by DependencyProperty, that contains the local value of each DependencyProperty, if it has been set.
The SetValue and GetValue methods that you implement in the setter and getter of the CLR property are basically lazy evaluation on steroids. Instead of storing and retrieving the value of the property in a backing field, they store and retrieve the value of the property in the value dictionary.
The magic of dependency properties is in what GetValue and SetValue actually do.
GetValue looks up the value for the property in the object's value dictionary. If it doesn't find it, it calls GetValue on the parent element, to get what the parent element thinks the value is. For instance, when you create a TextBox in a Window, anything that looks at the TextBox's FontFamily is actually calling GetValue. Unless you've explicitly set the font, there's no entry in its dictionary for that property. So GetValue asks the parent element for the value. The parent element may or may not have FontFamily set; if not, its call to GetValue to returns the value from its parent. And so on, until the Window object is reached and the actual FontFamily value is found.
If you set FontFamily on the TextBox, SetValue stores the value in the value dictionary. The next time anything needs to get the value of the FontFamily for that TextBox, GetValue finds the value in the dictionary and returns it, so it doesn't need to ask the parent element.
If you set FontFamily on the Window, SetValue not only updates the value in Window's value dictionary, it fires off a property-change event that everything dependent on the property hears. (That's why they're called dependency properties, remember.) And if the thing depending on the property is itself a dependency property, it fires off its own property-change events. This is how it is that changing the FontFamily on the Window changes the font for every control in the window and also prompts WPF to re-render the controls that have changed.
Attached properties work using the same kind of approach. Any object that can have attached properties has a dictionary that the attached properties' values are stored in. When you set Grid.Column on a CheckBox in XAML, you're just adding an entry to that CheckBox's dictionary. When the Grid needs to know what column the CheckBox is in, it looks the value up from that dictionary. When you set Grid.IsSharedSizeScope to True on an object, that object's dictionary will contain a new property - a dictionary that contains widths/heights for each SharedSizeKey.
I should emphasize that this is my mental model. I haven't sat down with Reflector and looked at the actual implementation of Register, GetValue, and SetValue to figure out how they actually work. I may be wrong about the details. But it's a model that accurately predicts how this stuff behaves, so it's good enough.
The concept of storing property values in dictionaries is pretty weird to C# programmers. It's old hat to Python programmers, though. In Python, all class properties - all objects, in fact - are stored in dictionaries, and so you can get to their value either through property accessors or just by looking them up. Dependency properties and attached properties are just another way in which .NET, having stolen everything Java had that was worth stealing, is now plundering Python. (Or from wherever Python plundered them from.) Learning Python has made me a much better C# programmer; I recommend it to any C# developer who hasn't done it yet.
Here is a tutorial on dependency properties http://www.wpftutorial.net/DependencyProperties.html that explains a little bit about how they work.
The short explanation of why the DependencyProperty object is in a static field is that it represents the description of the property, not the value of the property. Each DependencyObject has a mapping from DependencyProperty objects to their values.
This is also how attached properties work. Because each DependencyObject is storing a mapping from any DependencyProperty to a value, any type can create a new DependencyProperty and set it on any existing DependencyObject.
just see this post by joshsmith it has some additional informatin in it
http://joshsmithonwpf.wordpress.com/2007/06/22/overview-of-dependency-properties-in-wpf/
You can see below a very basic example of dependency property that creates a custom control text box in which space will be not allowed means user can not type space into text box.
1) Create a class with the name of ValidatedTextBox and write the following code in this class file:
public class ValidatedTextBox : TextBox
{
public ValidatedTextBox()
{
}
public static readonly DependencyProperty IsSpaceAllowedProperty =
DependencyProperty.Register("IsSpaceAllowed", typeof(bool), typeof(ValidatedTextBox));
public bool IsSpaceAllowed
{
get { return (bool)base.GetValue(IsSpaceAllowedProperty); }
set { base.SetValue(IsSpaceAllowedProperty, value); }
}
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
base.OnPreviewKeyDown(e);
if (!IsSpaceAllowed && (e.Key == Key.Space))
{
e.Handled = true;
}
}
}
2) Now use the above control into your .XAML file
a) Add namespace of custom control text box like below:
xmlns:CustomControls="clr-namespace: ValidatedTextBox;assembly= ValidatedTextBox "
b) Now, use custom control text box like below:
<CustomControls:ValidatedTextBox IsSpaceAllowed="False" x:Name="MyTextBox" />
It will create a custom control text box that will not allow space. So, Basically Dependency property allows to add feature, extend feature of any control.
I have yet to find a "nice" way to do two way databinding in .Net.
The one thing I don't like for example in the present asp.net two way databinding is doing the binding in the aspx page is no compile time checking, ie:
<asp:TextBox ID="TitleTextBox"
runat="server" Text='<%# Bind("Title_oops_spelled_wrong") %>'>
I would like to have something like this:
Class Binder
Public Sub BindControl(ctl As Control, objectProperty As ???????)
'// Add ctl and objectProperty to a collection
End Sub
What I don't know is possible is, how to receive the objectProperty in my example; I want to receive a reference (ie: a pointer) to the property, so later, via this reference, I can either read from or write to the property.
Can this somehow be done with delegates perhaps??
UPDATE:
Note, I want to add the control reference to a binding collection, this collection would then be used for binding and unbinding.
Is there a reason that you want to avoid using the .NET data binding mechanism? It handles keeping parity between the control's value and the class's property value already, and provides rich design-time support.
You can interface with the data binding engine in two ways: either programatically or through the designer. To do basic data binding programatically is trivial. Say I have a class named "FooClass" with a string property named "MyString". I have a TextBox named myTxtBox on a form with an instance of FooClass called foo and I want to bind it to the MyString property:
myTxtBox.DataBindings.Add("Text", foo, "MyString");
Executing this will cause updates to the TextBox to get assigned to the property, and changes to the property from elsewhere will be reflected in the TextBox.
For more complex data binding scenarios, you'll probably want to create an Object Data Source in your project and put a BindingSource on your form. If you need help with specific steps in creating the data source I can help, but in general you'll create the source in your project and select the class to which you want to bind. You can then place a BindingSource on your form, point it at your object project data source, then use the Visual Studio designer to bind properties for your controls to properties on your object. You then set the DataSource property in your code to an instance of the class or collection to which you want to bind.
As a side note, as far as I am aware there is no "property delegate", as properties are actually function pairs (a get_ and a set_).
UPDATE:
As I read your comments, I'd like to point out that .NET data binding, even at the control level, does NOT automatically use reflection. Data binding is built around type descriptors and property descriptors, both for the bound control and the data source. It's true that if one or both of these sides does not implement specific property and type description then reflection will be used, but either side is more than free to provide its own description profile which would NOT use reflection.
The Bind is not a method and there is no some object behind the scene holding binding relationship. It's just a "magic" word that page parser uses to generate code behind. Essentially, it translates into Eval and control building code. The Eval, on the other hand, will use reflection to access bound item's properties.
If I understand correctly what you want, read-only property binding already works. Assuming you have a property Title in your class:
<asp:TextBox ID="TitleTextBox" runat="server" Text='<%# Title %>' />
For two-way binding, you'd have to either create your own Template or reflect existing one and pass the ExtractTemplateValuesMethod method and assign the DataBinding event to your control. This is where .NET uses Eval, which you'd replace with the property assignment.
In my opinion, that is what the DataBinding event is for.
However, if you question is more about whether one can have a reference to a property, then I'm afraid not. There is no property per say. You have to methods (get and set) and an entry in the metadata. You could store a reference to the object and property name, but then you'd have to use reflection.
You could use the delegates, but that would take you back to the same code as the one .NET generates, which is defining ExtractTemplateValuesMethod and doing DataBinding anyhow.
One solution would be to pass objectProperty ByRef.
If you want compile time type checking you would need to overload BindControl for any types that you plan on using. For example:
Public Sub BindControl(ctl As ITextControl, ByRef objectProperty As String)
objectProperty = ITextControl.Text
End Sub
Public Sub BindControl(ctl As ITextControl, ByRef objectProperty As Integer)
Integer.TryParse(TextControl.Text, objectProperty)
End Sub
..