【问题标题】:Binding to attributes绑定到属性
【发布时间】:2012-09-19 10:27:28
【问题描述】:

我有课

public class Car 
{
    [Description("name of the car")]
    public string Name { get; set; }

    [Description("age of the car")]
    public int Age { get; set; }
}

是否有可能将描述属性绑定到标签内容。我正在寻找的解决方案不需要实例化 Car 对象。

【问题讨论】:

  • 您不应该这样做,这是一种丑陋的填充 UI 元素的方式。您到底想实现什么 - 根据绑定的内容自动填充一个窗口?
  • 是的,我想让 Windows 中的所有标签都从类属性属性“描述”中获取它们的内容。此属性也用于验证目的。
  • 您应该将标签绑定到字符串资源文件中的文本。如果您的绑定项目可以更改,请使用 DataTemplates。

标签: c# wpf xaml data-binding


【解决方案1】:

它不会是一个正确的绑定(无论如何这对于静态数据不是必需的),但您可以轻松地创建一个 MarkupExtension 来检索它,只需传递类型和属性名称并通过反射获取它。

大纲类似于:

public Type Type { get; set; }
public string PropertyName { get; set; }

ProvideValue: Type.GetProperty(PropertyName)
                  .GetCustomAttributes(true)
                  .OfType<DescriptionAttribute>()
                  .First()
                  .Description
<!-- Usage example -->
Text="{me:Description Type=local:Car, PropertyName=Name}"

【讨论】:

  • 我很矛盾——你向他展示了一种方法,但你也让他能够创建属于魔多深处的代码......
  • @slugster:我不知道,也有人使用类似本地化的DisplayName 属性,你能解释一下为什么会有问题吗?
  • 本地化似乎远离 OP 的想法,我怀疑他这样做是因为他避免或不了解数据模板。在没有对大局做出任何解释的情况下,我感觉到即将发生的火车失事。
  • @slugster:在对问题的评论中提到了“标签”,因此如果它仅用于此目的,而不是用于实际数据,它应该绑定到标签旁边的某个控件,它应该没问题...
【解决方案2】:

您不能,因为它是属性的元数据。您可以通过创建自定义绑定类来解决问题。

【讨论】:

    【解决方案3】:

    1 你创建一个Converter

    public sealed class PropertyDescriptionConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                if (value == null)
                    return Binding.DoNothing;
    
                string propertyName = parameter as string;
                if (String.IsNullOrEmpty(propertyName))
                    return new ArgumentNullException("parameter").ToString();
    
                Type type = value.GetType();
    
                PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
                if (property == null)
                    return new ArgumentOutOfRangeException("parameter", parameter,
                        "Property \"" + propertyName + "\" not found in type \"" + type.Name + "\".").ToString();
    
                if (!property.IsDefined(typeof(DescriptionAttribute), true))
                    return new ArgumentOutOfRangeException("parameter", parameter,
                        "Property \"" + propertyName + "\" of type \"" + type.Name + "\"" +
                        " has no associated Description attribute.").ToString();
    
                return ((DescriptionAttribute)property.GetCustomAttributes(typeof(DescriptionAttribute), true)[0]).Description;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotSupportedException();
            }
        }
    

    2 你插入你的资源

        <Window.Resources>
            <local:PropertyDescriptionConverter x:Key="PropertyDescriptionConverter" />
        </Window.Resources>
    

    3 添加此绑定

    "{Binding ConverterParameter=Name, Converter={StaticResource PropertyDescriptionConverter}}"
    

    【讨论】:

    • 问题明确指出没有实例。
    【解决方案4】:

    使用字符串常量代替字符串字面量来设置属性参数:

    public class Car
    {
        public const string CarNamePropertyDescription = "name of the car";
        
        [Description(CarNamePropertyDescription)]
        public string Name { get; set; }
    }
    

    可以通过 {x:Static} 扩展从 xaml 访问常量(不需要绑定,因为属性不会在运行时更改):

    <Label Content="{x:Static namespace:Car.CarNamePropertyDescription}"/>
    

    【讨论】:

      【解决方案5】:

      然后创建一个reader类,读取类的属性,绑定reader类的属性。例如

      public class Reader
      {
         public Dictionary<string, string> Description {get; set;}
      }

      【讨论】:

        猜你喜欢
        • 2010-11-26
        • 1970-01-01
        • 1970-01-01
        • 2014-07-04
        • 1970-01-01
        • 2017-11-08
        相关资源
        最近更新 更多