Databinding to CLR property in code-behind

前端 未结 5 1354
隐瞒了意图╮
隐瞒了意图╮ 2021-02-15 20:18

Binding to a Dependency Property is easy in code-behind. You just create a new System.Windows.Data.Binding object, and then call the target dependency object\'s

相关标签:
5条回答
  • 2021-02-15 21:05

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

    Here's how you do it in the code behind:

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

    In this case, the Binding object represents the information about the Source: What object is the source, which property of that object is the one you're interested in. BindingOperations.SetBinding is a static method which specifies which DependencyProperty on which DependencyObject is the target of the binding (arguments 2 & 1, respectively), and the Binding to use to get at the source.

    HTH

    Tony

    0 讨论(0)
  • 2021-02-15 21:16

    Wait. Are you trying to bind 2 CLR properties?? Let me say such thing is impossible to achieve in normal way. eg. no kind of hardcore hack that can make your whole application unstable. One side of binding MUST be DependencyProperty. Period.

    0 讨论(0)
  • 2021-02-15 21:22

    For this to be possible, the property must be one for which you are writing the setter (so, not a property defined in code you can't change).
    Then the solution is Implement Property Change Notification.

    Sample code from above link:

    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 that implementation, each property setter must call

    OnPropertyChanged("YourPropertyName");
    

    Or for a slightly different implementation, that avoids having to re-enter 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'm working in Xamarin Forms, but I think those are all useable from WPF as well; they are based on System.ComponentModel namespace.)

    0 讨论(0)
  • 2021-02-15 21:24

    If I understand your question correctly you have a FrameworkElement that exposes a plain old ordinary property that isn't backed up as a Dependency property. However you would like to set it as the target of a binding.

    First off getting TwoWay binding to work would be unlikely and in most cases impossible. However if you only want one way binding then you could create an attached property as a surrogate for the actual property.

    Lets imagine I have a StatusDisplay framework element that has a string Message property that for some really dumb reason doesn't 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 its Message property modified directly for any reason the state of this surrogate will no longer match. Still that may not matter for your purposes.

    0 讨论(0)
  • 2021-02-15 21:24

    Binding targets MUST be dependency properties! That's the only requirement for databinding to work!

    Read more here:

    • http://msdn.microsoft.com/en-us/library/ms531387(VS.85).aspx
    • http://msdn.microsoft.com/en-us/library/ms752347.aspx
    0 讨论(0)
提交回复
热议问题