Linking CLR Data in Code

Associating a dependent property is easy in encoding. You simply create a new System.Windows.Data.Binding object, and then call the SetBinding task SetBinding .

But how do you do this when the property we are binding is a CLR property and you cannot provide a DependencyProperty argument for SetBinding ?

EDIT: The object implements INotifyPropertyChanged , if relevant.

+7
c # data-binding wpf silverlight code-behind
source share
5 answers

Binding targets MUST be dependent properties! This is the only requirement for data binding!

More details here:

+4
source share

If I understand your question correctly, you have a FrameworkElement that provides a plain old plain regular property that is not reserved as a Dependency property. However, you would like to set it as the target of the binding.

First of all, getting TwoWay to work would be unlikely and impossible in most cases. However, if you only need one way to bind, you can create an attached property as a surrogate for the actual property.

Suppose I have an element in the StatusDisplay structure that has a string Message property that, for some really dumb reason, does not support Message as a dependency property.

 public static StatusDisplaySurrogates { public static string GetMessage(StatusDisplay element) { if (element == null) { throw new ArgumentNullException("element"); } return element.GetValue(MessageProperty) as string; } public static void SetMessage(StatusDisplay element, string value) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(MessageProperty, value); } public static readonly DependencyProperty MessageProperty = DependencyProperty.RegisterAttached( "Message", typeof(string), typeof(StatusDisplay), new PropertyMetadata(null, OnMessagePropertyChanged)); private static void OnMessagePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { StatusDisplay source = d as StatusDisplay; source.Message = e.NewValue as String; } } 

Of course, if the StatusDisplay control has the Message property changed for any reason, the state of this surrogate will no longer match. However, this may not be relevant to your goals.

0
source share

Wait. Are you trying to bind 2 properties of the CLR? Let me say that this cannot be achieved in the usual way. eg. without any hardcore hack that could make your application unstable. One side of the binding MUST be a DependencyProperty. Period.

0
source share

You can associate the CLR property with DepenencyProperty on a control, for example. In this cae, the CLR property is the SOURCE of the binding, and DependencyProperty is the TARGET binding. For it to work, a class with the CLR property must implement INotifyPropertyChanged.

Here's how you do it in code:

 Binding canModifyBinding = new Binding(); canModifyBinding.Source = LastRecord; canModifyBinding.Path = new PropertyPath( "CanModify" ); BindingOperations.SetBinding( this, CanModifyProperty, canModifyBinding ); 

In this case, the Binding object represents information about the source: which object is the source, which property of this object is the one that interests you. BindingOperations.SetBinding is a static method that determines which DependencyProperty on which DependencyObject is the target of the binding (arguments 2 and 1 respectively) and the binding to use in the source.

NTN

Tony

0
source share

To make this possible, the property must be the one for which you are writing a setter (so this is not a property defined in the code that you cannot change).
Then the solution is a “ Property Change Notification” .

Sample code from the link above:

 using System.ComponentModel; namespace SDKSample { // This class implements INotifyPropertyChanged // to support one-way and two-way bindings // (such that the UI element updates when the source // has been changed dynamically) public class Person : INotifyPropertyChanged { private string name; // Declare the event public event PropertyChangedEventHandler PropertyChanged; public Person() { } public Person(string value) { this.name = value; } public string PersonName { get { return name; } set { name = value; // Call OnPropertyChanged whenever the property is updated OnPropertyChanged("PersonName"); } } // Create the OnPropertyChanged method to raise the event protected void OnPropertyChanged(string name) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(name)); } } } } 

In this implementation, each interlocutor should call

 OnPropertyChanged("YourPropertyName"); 

Or for a slightly different implementation that avoids re-entering the property name as a string parameter, see My answer here .
There I also mention Fody / PropertyChanged, TinyMvvm, and MvvmCross as libraries that can help implement this pattern.
(I work in Xamarin Forms, but I think that they are all suitable for WPF, they are based on the System.ComponentModel namespace.)

0
source share

All Articles