簡體   English   中英

模型屬性的屬性通過視圖模型查看 - 如何?

[英]Attributes of model properties goes to view through view model - how to?

如何將模型屬性的屬性綁定到視圖?

我有一個模型,例如:

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

怎么弄?

由於只能使用反射檢索屬性屬性,因此必須提供一些方法將“(類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

顯然,這個解決方案需要進行推廣,以便可以方便地在不同的模型和屬性類型中使用; 將它打包在值轉換器中是個好主意。

一種可能的解決方案是添加輔助類並將該類的實例作為轉換器參數傳遞。 必須在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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM