原文:为普通Object添加类似AttachedProperty的属性
为普通Object添加类似AttachedProperty的属性
周银辉
我们知道,在WPF中对应一个DependencyObject,我们很容易通过AttachedProperty来为类型附加一个属性。但对于普通的Object而言,这就不可行了。
我现在遇到这样一个问题,下面有一个继承与Object(而不是DependencyObject)的普通类:
namespace CustomAttachedProperty { public class People { public string Name { get; set; } public People(string name) { Name = name; } public override string ToString() { return Name; } } }
我需要它在某些情况下具有IsKeyPerson这个属性,当这个属性为true时,界面会将名称标记为红色。但我没有办法去修改这个People的实现。如果它是DependencyObject就好了,可惜他不是。
我的展示这个People类的界面大概会写成这个样子:
<DataTemplate DataType="customAttachedProperty:People"> <TextBlock x:Name="TextBlock" Text="{Binding Name}"/> <DataTemplate.Triggers> <DataTrigger 如果IsKeyPerson为true> <Setter TargetName="TextBlock" Property="Foreground" Value="Red"/> </DataTrigger> </DataTemplate.Triggers> </DataTemplate>
using System.Collections.Generic; namespace CustomAttachedProperty { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow { public MainWindow() { InitializeComponent(); Test(); } public static string IsKeyPersonPropertyString = "IsKeyPerson"; //Test用于DataTemplate的Binding private void Test() { var peopleList = new List<People> {new People("ZhangSan"), new People("LiSi")}; var wangwu = new People("WangWu"); AttachedPropertyBuffer.SetPropertyValue(wangwu,"IsKeyPerson", true); peopleList.Add(wangwu); MyListBox.ItemsSource = peopleList; } } }
<Window x:Class="CustomAttachedProperty.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:customAttachedProperty="clr-namespace:CustomAttachedProperty" Title="MainWindow" Height="350" Width="525" > <Window.Resources> <customAttachedProperty:AttachedPropertyBufferConverter x:Key="AttachedPropertyBufferConverter"/> <!--方式1--> <!--<Style TargetType="ListBoxItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ListBoxItem"> <TextBlock x:Name="TextBlock" Text="{Binding}" Foreground="{TemplateBinding Foreground}" /> <ControlTemplate.Triggers> <DataTrigger Binding="{Binding Path=., Converter={StaticResource AttachedPropertyBufferConverter} , ConverterParameter='{x:Static customAttachedProperty:MainWindow.IsKeyPersonPropertyString}' }" Value="True"> <Setter TargetName="TextBlock" Property="Foreground" Value="Red"/> </DataTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>--> </Window.Resources> <Grid> <ListBox x:Name="MyListBox"> <!--方式2--> <ListBox.ItemTemplate> <DataTemplate DataType="customAttachedProperty:People"> <TextBlock x:Name="TextBlock" Text="{Binding Name}"/> <DataTemplate.Triggers> <DataTrigger Binding="{Binding Path=., Converter={StaticResource AttachedPropertyBufferConverter} ,ConverterParameter='IsKeyPerson' }" Value="True"> <Setter TargetName="TextBlock" Property="Foreground" Value="Red"/> </DataTrigger> </DataTemplate.Triggers> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Window>
using System; using System.Collections.Generic; using System.Globalization; using System.Windows.Data; namespace CustomAttachedProperty { /// <summary> /// 属性存储区 /// </summary> public static class AttachedPropertyBuffer { private static readonly Dictionary<object, Dictionary<string, object>> BufferDictionary = new Dictionary<object, Dictionary<string, object>>(); public static void SetPropertyValue(object obj, string propertyName, object value) { if (BufferDictionary.ContainsKey(obj)) { var innerDic = BufferDictionary[obj]; if (innerDic.ContainsKey(propertyName)) { innerDic[propertyName] = value; } else { innerDic.Add(propertyName, value); } } else { var innerDic = new Dictionary<string, object> {{propertyName, value}}; BufferDictionary.Add(obj, innerDic); } } public static object GetPropertyValue(object obj, string propertyName) { if (BufferDictionary.ContainsKey(obj)) { var innerDic = BufferDictionary[obj]; if (innerDic.ContainsKey(propertyName)) { return innerDic[propertyName]; } } return default(object); } } public class AttachedPropertyBufferConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return AttachedPropertyBuffer.GetPropertyValue(value, parameter.ToString()); ; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } }
具体如何实现的,下载代码:http://files.cnblogs.com/zhouyinhui/CustomAttachedPropertySln.rar