【问题标题】:Windows Forms data bindingWindows 窗体数据绑定
【发布时间】:2015-07-17 17:51:59
【问题描述】:

所以,我的问题是关于 Windows 表单数据绑定背后的确切方法。

我编写了一个简单的代码,在其中创建了一个视图、一个 IViewModel 接口和一个 ViewModel。

interface IVM
{
}

public class Vm : IVM
{
    int number;
    public int Number
    {
        get
        {
            return this.number;
        }

        set
        {
            this.number = value;
        }
    }
}

表格如下:

public partial class Form1 : Form
{
    private IVM vm;

    public Form1()
    {
        InitializeComponent();
        this.vm = new Vm();

        this.iVMBindingSource.DataSource = this.vm;
    }
}

相关的设计师部分是:

this.textBox1.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.iVMBindingSource, "Number", true));
...
this.iVMBindingSource.DataSource = typeof(WindowsFormsApplication1.IVM);

可以清楚的看到IViewModel接口并没有发布Number属性,但是具体的ViewModel类有一个Number属性。

虽然在设计时我无法使用设计器绑定属性(因为 IVM 没有 Number 属性),但我可以手动将“iVMBindingSource - Number”写入文本框的 Test 属性,以进行绑定。

我的问题是,绑定到底是如何工作的?为什么我在尝试访问 IVM 不存在的 Number 属性时没有收到运行时错误? (我测试过,它实际上正确地改变了 VM 的 Number 属性)

它是否使用某种反射?这个“神奇”的绑定字符串是如何工作的?

感谢您的回答!

【问题讨论】:

  • 反思,我相信。还有一些用于通知更改的支持事件(您的属性不会引发这些事件,因此您的绑定是一次性的)。
  • 我知道,我这次不关心 INotifyPropertyChanged,只是想知道它是如何工作的

标签: c# winforms data-binding solid-principles


【解决方案1】:

Jup 它是通过反射完成的。我刚刚检查了代码,绑定是由Binding 类完成的。有一个名为CheckBindings 的方法可确保您要绑定的属性可用。它基本上是这样工作的:

if (this.control != null && this.propertyName.Length > 0)
{
  // ...certain checks...
  // get PropertyDescriptorCollection (all properties)
  for (int index = 0; index < descriptorCollection.Count; ++index)
  {
    // select the descriptor for the requested property
  }
  // validation
  // setup binding
}

正如 Ike 提到的,您可以在此处找到源代码: http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Binding.cs,3fb776d540d0e8ac

MSDN 参考:https://msdn.microsoft.com/en-us/library/system.windows.forms.binding(v=vs.110).aspx

【讨论】:

  • 可以找到Bindighere的源码
  • @ike 谢谢,我已将其添加到答案中
  • 谢谢你,一个非常好的答案。接受。
【解决方案2】:

正如 derape 已经提到的,Binding 使用反射。它必须使用反射,因为它对您正在使用的类一无所知。评估将在运行时完成。由于您的具体类型Vm 获得了指定的属性Number,反射将返回它并且满足Binding 类。只要属性名有效,绑定真的很灵活。

另一方面,当您使用设计器时,它无法知道您将使用哪种具体类型。因此它只允许您使用公共基础IVM 的属性。如果您手动输入字符串,将跳过设计时评估并将输入传递给绑定构造函数。

如果您想使用设计器支持,只需使用具体类型,或者如果您不知道具体类型但需要属性Number,只需创建一个新接口并派生自IMV.

【讨论】:

  • 我不想使用 concere 类型,因为我想在未来实现依赖倒置原则。我只会将 Number 作为接口道具发布。感谢您的回答!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-11
  • 2017-02-27
  • 1970-01-01
  • 1970-01-01
  • 2011-07-08
  • 2011-01-17
相关资源
最近更新 更多