【问题标题】:How to get the attributes of a bound object's property?如何获取绑定对象的属性?
【发布时间】:2017-11-21 16:31:03
【问题描述】:

我有一个User 类:

public partial class User : INotifyPropertyChanged
{
    private string forename;

    [MaxLength(10)]
    public string Forename
    {
        get => forename;
        set
        {
            forename = value;
            OnPropertyChanged("forename");
        }
    }

    public User(string forename)
    {
        Forename = forename;
    }
}

我还有一个TextBoxTextBoxText 属性绑定到 User 对象:

textBox.DataBindings.Add("Text", new User("Michael"), "Forename");

我想通过TextBox 获取ForenameMaxLength 属性。该怎么做?


注意:上面的代码是我真实代码的简化。

【问题讨论】:

  • 你不能声明式地这样做,但你可以do it via reflection
  • 由于您在代码中设置数据绑定,因此为您创建一个数据绑定方法,并在该方法中将 maxlength 应用于控件。要获取最大长度,除了反射,还可以使用类型描述符。
  • @RezaAghaei - 你能详细说明一下答案吗?

标签: c# winforms data-binding


【解决方案1】:

您可以使用反射或类型描述符来获取有关类型的信息。您需要在何时何地执行此操作取决于实施。

由于数据绑定的数据源可以是任何对象,例如类或绑定源,因此依赖类型描述符会更加灵活和可扩展。例如,如果您想调用一个方法来应用 maxlength,只需将 TextBox 传递给这样的方法:

ApplyMaxLengthToTextBox(textBox1);

那么你可以这样创建方法:

//using System.Linq;
public void ApplyMaxLengthToTextBox(TextBox txt)
{
    var binding = txt.DataBindings["Text"];
    if (binding == null)
        return;
    var bindingManager = binding.BindingManagerBase;
    var datasourceProperty = binding.BindingMemberInfo.BindingField;
    var propertyDescriptor = bindingManager.GetItemProperties()[datasourceProperty];
    var maxLengthAttribute = propertyDescriptor.Attributes.Cast<Attribute>()
        .OfType<MaxLengthAttribute>().FirstOrDefault();
    if (maxLengthAttribute != null)
        txt.MaxLength = maxLengthAttribute.Length;
}

在绑定到对象时对其进行测试:

textBox1.DataBindings.Add("Text", new MySampleModel(), "SomeProperty");
ApplyMaxLengthToTextBox(textBox1);

在绑定到BindingSource 时对其进行测试:

var bs = new BindingSource();
bs.DataSource = new MySampleModel();
textBox1.DataBindings.Add("Text", bs, "SomeProperty");
ApplyMaxLengthToTextBox(textBox1);

【讨论】:

  • 这个答案很棒,我相信它会对未来的读者有所帮助。但是,我对它背后的很多想法并不熟悉。 ExpressionFuncMemberExpression 等等。您能否添加一个不涉及扩展方法等的更简单的代码 sn-p ?像@touchofevil 写的东西,但没有硬编码?非常感谢!
  • 现在它是最简单的解决方案,它也尊重 Windows 窗体数据绑定规则。数据绑定时反射不是一个好主意。数据绑定适用于类型描述符和属性描述符。
  • PropertyDescriptor 在某种程度上等同于PropertyInfo。您从TypeDescriptor.GetProperties() 获取属性描述符,而从Type.GetProperties() 获取属性信息。欲了解更多信息,请查看Type Descriptor Overview
  • 除了数据绑定在类型描述之上工作之外,作为另一个好处,使用类型描述符机制为您的应用程序带来了很大的可扩展性。您可以将元数据与模型类分开。有关更多信息,请查看我的帖子here
  • 在当前的答案中,您不需要了解有关 TypeDescriptor 的任何信息。您只需要知道Binding 对象的BindingManagerBase 属性,它有一个GetItemProperties,它返回模型(数据源)具有的属性列表。这对你来说已经足够了。
【解决方案2】:

你可以试试下面的sn-p

var prop = typeof(User).GetProperty("Forename");
var att = prop.GetCustomAttributes(typeof(MaxLength), false);

【讨论】:

  • 谢谢!您已经硬编码了User 类型、属性名称ForenameMaxLength 属性。我想使用我的textBox 对象来获取所有这些信息,因为它绑定到User 对象。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
  • 2018-04-06
相关资源
最近更新 更多