繁体   English   中英

数据绑定到代码隐藏中的目标 CLR 属性

[英]Databinding to a target CLR property in code-behind

绑定到依赖属性在代码隐藏中很容易。 您只需创建一个新的System.Windows.Data.Binding对象,然后调用目标依赖对象的SetBinding方法。

但是,当我们绑定的属性是 CLR 属性并且您无法为SetBinding提供DependencyProperty参数时,您将如何执行此SetBinding 有没有办法使用 CLR 属性作为绑定目标?

编辑:如果相关,该对象实现INotifyPropertyChanged

绑定目标必须是依赖属性! 这是数据绑定工作的唯一要求!

在此处阅读更多信息:

为此,该属性必须是您正在为其编写 setter 的属性(因此,不是您无法更改的代码中定义的属性)。
那么解决方案是实施属性更改通知

来自上面链接的示例代码:

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));
          }
      }
  }
}

在该实现中,每个属性设置器必须调用

OnPropertyChanged("YourPropertyName");

或者对于稍微不同的实现,避免必须重新输入属性名称作为字符串参数,请参阅我的答案here
在那里,我还提到了 Fody/PropertyChanged、TinyMvvm 和 MvvmCross 作为可以帮助实现此模式的库。
(我在 Xamarin Forms 中工作,但我认为这些都可以从 WPF 中使用;它们基于 System.ComponentModel 命名空间。)

如果我正确理解了您的问题,那么您有一个FrameworkElement ,它公开了一个没有作为 Dependency 属性备份的普通旧属性。 但是,您希望将其设置为绑定的目标。

首先让 TwoWay 绑定工作不太可能,在大多数情况下是不可能的。 但是,如果您只想要一种方式绑定,那么您可以创建一个附加属性作为实际属性的代理。

假设我有一个StatusDisplay框架元素,它有一个字符串Message属性,由于某些非常愚蠢的原因,它不支持Message作为依赖属性。

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;
    }
}

当然,如果StatusDisplay控件由于任何原因直接修改了它的Message属性,则此代理的状态将不再匹配。 尽管如此,这对您的目的来说可能并不重要。

等等。 您是否要绑定 2 个 CLR 属性? 让我说这样的事情以正常方式是不可能实现的。 例如。 没有一种硬核黑客可以使您的整个应用程序不稳定。 绑定的一侧必须是 DependencyProperty。 期间。

例如,您可以将 CLR 属性绑定到控件上的 DepenencyProperty。 在这个案例中,CLR 属性是绑定的 SOURCE,而 DependencyProperty 是绑定的 TARGET。 为了使其工作,具有 CLR 属性的类必须实现 INotifyPropertyChanged。

以下是您在后面的代码中的操作方法:

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

在这种情况下, Binding 对象表示有关 Source 的信息:哪个对象是源,该对象的哪个属性是您感兴趣的。 BindingOperations.SetBinding 是一个静态方法,它指定哪个 DependencyProperty 是哪个 DependencyObject绑定的目标(分别为参数 2 和 1),以及用于获取源的 Binding。

HTH

托尼

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM