如何将模型属性的属性绑定到视图?
我有一个模型,例如:
class MyModel
{
[Display(
ResourceType = typeof(Resources.Strings),
Name = "MyName",
Description = "MyDescription")]
public double MyProperty { get; set; }
}
我的视图模型是这样的(没有异常):
public class MyVM
{
private Models.MyModel model;
public string MyVMProperty
{
get { return model.MyProperty.ToString(); }
set
{
// some usual code with parsing a value from textbox...
}
}
}
在视图中,我想绑定模型属性属性中的数据。像这样:
<Grid Name="myGrid">
<TextBox
Text="{Binding Path=MyVMProperty}"
/>
<TextBlock
Text="{Binding Path=MyVM.model.MyProperty.DisplayAttribute.Name}"
/>
<TextBlock
Text="{Binding Path=MyVM.model.MyProperty.DisplayAttribute.Description}"
/>
</Grid>
我在代码中的某处:
myGrid.DataContext = new MyVM();
如何获得它?
答案 0 :(得分:1)
由于属性属性只能使用反射来检索,因此您必须提供一些方法将“(类OR对象)+属性名称”元组转换为公开这些属性值的内容。
一个非常具体的解决方案看起来像
public DisplayAttribute MyVMPropertyDisplayAttribute
{
get
{
var prop = typeof(MyModels.Model).GetProperty("MyProperty");
var attr = prop.GetCustomAttributes(typeof(DisplayAttribute));
return attr.Cast<DisplayAttribute>().Single();
}
}
然后你可以绑定到例如MyVMPropertyDisplayAttribute.Name
。
显然,这个解决方案需要进行推广,以便可以方便地在不同的模型和属性类型中使用;将它打包在值转换器中是个好主意。
答案 1 :(得分:1)
可能的解决方案之一是添加辅助类并将该类的实例作为转换器参数传递。必须在XAML中手动初始化实例。该实例包含获取模型实例的属性的属性值所需的所有数据。该解决方案是通用的,并且转换器逻辑内部没有硬编码数据。转换器的“值”参数也不是必需的。
所以,结果如下:
与视图模型在同一程序集中的某些内容。转换器和辅助类(简化 - 没有任何空检查等):
namespace MyProject.Converters
{
public class MetadataParameters
{
public Type ModelType { get; set; }
public string ModelProperty { get; set; }
public Type AttributeType { get; set; }
public string AttributeProperty { get; set; }
}
public class MetadataConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var mp = parameter as MetadataParameters;
var modelPropertyInfo = mp.ModelType.GetProperty(mp.ModelProperty);
var attribute = modelPropertyInfo
.GetCustomAttributes(true)
.Cast<Attribute>()
.FirstOrDefault(memberInfo => memberInfo.GetType() == mp.AttributeType);
var attributeProperty = attribute.GetType().GetProperty(mp.AttributeProperty);
return attributeProperty.GetValue(attribute, null);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
在资源文件(XAML)中:
xmlns:converters="clr-namespace:MyProject.Converters"
...
<converters:MetadataConverter x:Key="metadataConverter" />
在视图文件中:
<!-- language: lang-xml -->
xmlns:converters="clr-namespace:MyProject.Converters"
xmlns:DataAnnotations="clr-namespace:System.ComponentModel.DataAnnotations;assembly=System.ComponentModel.DataAnnotations"
xmlns:Models="clr-namespace:MyProject.Models"
...
<TextBlock
<TextBlock.Text>
<Binding
Mode="OneWay"
Converter="{StaticResource metadataConverter}">
<Binding.ConverterParameter>
<converters:MetadataParameters
ModelType="{x:Type Models:Model}"
ModelProperty="ModelProperty"
AttributeType="{x:Type DataAnnotations:DisplayAttribute}"
AttributeProperty="Name" />
</Binding.ConverterParameter>
</Binding>
</TextBlock.Text>
</TextBlock>