稳扎稳打Silverlight(65) - 5.0绑定之通过 ICustomTypeProvider 绑定动态生成的属性
作者:webabcd
介绍
Silverlight 5.0 绑定
- 绑定动态生成的属性
在线DEMO
http://www.cnblogs.com/webabcd/archive/2012/03/05/2379862.html
示例
Binding/DynamicProperty.xaml
<navigation:Page x:Class="Silverlight50.Binding.DynamicProperty"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="640" d:DesignHeight="480"
Title="DynamicProperty Page"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<Grid x:Name="LayoutRoot">
<sdk:DataGrid Name="dgProducts" AutoGenerateColumns="True" />
</Grid>
</navigation:Page>
Binding/DynamicProperty.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
namespace Silverlight50.Binding
{
public partial class DynamicProperty : Page
{
public DynamicProperty()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(DynamicProperty_Loaded);
}
void DynamicProperty_Loaded(object sender, RoutedEventArgs e)
{
// 动态地为 Product 类型增加属性
Product.AddProperty("Age", typeof(int));
Product.AddProperty("Favorite", typeof(bool));
Product product = new Product { Name = "3DS", Category = "游戏机", Price = 1100d };
// 为 Product 中的动态生成的属性赋值
product.SetPropertyValue("Age", 1);
product.SetPropertyValue("Favorite", true);
List<Product> products = new List<Product>();
products.Add(product);
// 由于 Product 实现了 ICustomTypeProvider 接口,所以动态生成的属性会被绑定到 DataGrid 控件上
dgProducts.ItemsSource = products;
}
// Product 实现了 ICustomTypeProvider 接口,实现此接口的话可以绑定动态生成的属性
class Product : CustomTypeHelper<Product>
{
public string Name { get; set; }
public string Category { get; set; }
public double Price { get; set; }
}
}
}
Binding/CustomTypeHelper.cs
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Reflection;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
namespace Silverlight50.Binding
{
/// <summary>
/// 实现了 ICustomTypeProvider 和 INotifyPropertyChanged 的自定义类型的帮助类
/// </summary>
public class CustomTypeHelper<T> : ICustomTypeProvider, INotifyPropertyChanged
{
private static List<CustomPropertyInfoHelper> _customProperties = new List<CustomPropertyInfoHelper>();
private Dictionary<string, object> _customPropertyValues;
private CustomType _ctype;
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public CustomTypeHelper()
{
_customPropertyValues = new Dictionary<string, object>();
foreach (var property in this.GetCustomType().GetProperties())
{
_customPropertyValues.Add(property.Name, null);
}
}
public static void AddProperty(string name)
{
if (!CheckIfNameExists(name))
_customProperties.Add(new CustomPropertyInfoHelper(name, typeof(String)));
}
public static void AddProperty(string name, Type propertyType)
{
if (!CheckIfNameExists(name))
_customProperties.Add(new CustomPropertyInfoHelper(name, propertyType));
}
public static void AddProperty(string name, Type propertyType, List<Attribute> attributes)
{
if (!CheckIfNameExists(name))
_customProperties.Add(new CustomPropertyInfoHelper(name, propertyType, attributes));
}
private static bool CheckIfNameExists(string name)
{
if ((from p in _customProperties select p.Name).Contains(name) || (from p in typeof(T).GetProperties() select p.Name).Contains(name))
throw new Exception("已存在同名属性:" + name);
else return false;
}
public void SetPropertyValue(string propertyName, object value)
{
CustomPropertyInfoHelper propertyInfo = (from prop in _customProperties where prop.Name == propertyName select prop).FirstOrDefault();
if (!_customPropertyValues.ContainsKey(propertyName))
throw new Exception("无此属性:" + propertyName);
if (ValidateValueType(value, propertyInfo._type))
{
if (_customPropertyValues[propertyName] != value)
{
_customPropertyValues[propertyName] = value;
NotifyPropertyChanged(propertyName);
}
}
else throw new Exception("值的类型错误或者对一个非空类型设置为 null");
}
private bool ValidateValueType(object value, Type type)
{
if (value == null)
// 引用类型可以被标记为 null
if (!type.IsValueType)
return true;
else
return (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>));
else
return type.IsAssignableFrom(value.GetType());
}
public object GetPropertyValue(string propertyName)
{
if (_customPropertyValues.ContainsKey(propertyName))
return _customPropertyValues[propertyName];
else
throw new Exception("无此属性:" + propertyName);
}
public PropertyInfo[] GetProperties()
{
return this.GetCustomType().GetProperties();
}
public Type GetCustomType()
{
if (_ctype == null)
{
_ctype = new CustomType(typeof(T));
}
return _ctype;
}
/// <summary>
/// 继承抽象类 Type,以实现自定义的 Type
/// </summary>
private class CustomType : Type
{
Type _baseType;
public CustomType(Type delegatingType)
{
_baseType = delegatingType;
}
public override Assembly Assembly
{
get { return _baseType.Assembly; }
}
public override string AssemblyQualifiedName
{
get { return _baseType.AssemblyQualifiedName; }
}
public override Type BaseType
{
get { return _baseType.BaseType; }
}
public override string FullName
{
get { return _baseType.FullName; }
}
public override Guid GUID
{
get { return _baseType.GUID; }
}
protected override TypeAttributes GetAttributeFlagsImpl()
{
throw new NotImplementedException();
}
protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
{
throw new NotImplementedException();
}
public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
{
return _baseType.GetConstructors(bindingAttr);
}
public override Type GetElementType()
{
return _baseType.GetElementType();
}
public override EventInfo GetEvent(string name, BindingFlags bindingAttr)
{
return _baseType.GetEvent(name, bindingAttr);
}
public override EventInfo[] GetEvents(BindingFlags bindingAttr)
{
return _baseType.GetEvents(bindingAttr);
}
public override FieldInfo GetField(string name, BindingFlags bindingAttr)
{
return _baseType.GetField(name, bindingAttr);
}
public override FieldInfo[] GetFields(BindingFlags bindingAttr)
{
return _baseType.GetFields(bindingAttr);
}
public override Type GetInterface(string name, bool ignoreCase)
{
return _baseType.GetInterface(name, ignoreCase);
}
public override Type[] GetInterfaces()
{
return _baseType.GetInterfaces();
}
public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
{
return _baseType.GetMembers(bindingAttr);
}
protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
{
throw new NotImplementedException();
}
public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
{
return _baseType.GetMethods(bindingAttr);
}
public override Type GetNestedType(string name, BindingFlags bindingAttr)
{
return _baseType.GetNestedType(name, bindingAttr);
}
public override Type[] GetNestedTypes(BindingFlags bindingAttr)
{
return _baseType.GetNestedTypes(bindingAttr);
}
public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
{
PropertyInfo[] clrProperties = _baseType.GetProperties(bindingAttr);
if (clrProperties != null)
{
return clrProperties.Concat(_customProperties).ToArray();
}
else
return _customProperties.ToArray();
}
protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
{
PropertyInfo propertyInfo = (from prop in GetProperties(bindingAttr) where prop.Name == name select prop).FirstOrDefault();
if (propertyInfo == null)
{
// 如果没有对应的clr属性则返回自定义属性
propertyInfo = (from prop in _customProperties where prop.Name == name select prop).FirstOrDefault();
}
return propertyInfo;
}
protected override bool HasElementTypeImpl()
{
throw new NotImplementedException();
}
public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
{
return _baseType.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
}
protected override bool IsArrayImpl()
{
throw new NotImplementedException();
}
protected override bool IsByRefImpl()
{
throw new NotImplementedException();
}
protected override bool IsCOMObjectImpl()
{
throw new NotImplementedException();
}
protected override bool IsPointerImpl()
{
throw new NotImplementedException();
}
protected override bool IsPrimitiveImpl()
{
return _baseType.IsPrimitive;
}
public override Module Module
{
get { return _baseType.Module; }
}
public override string Namespace
{
get { return _baseType.Namespace; }
}
public override Type UnderlyingSystemType
{
get { return _baseType.UnderlyingSystemType; }
}
public override object[] GetCustomAttributes(Type attributeType, bool inherit)
{
return _baseType.GetCustomAttributes(attributeType, inherit);
}
public override object[] GetCustomAttributes(bool inherit)
{
return _baseType.GetCustomAttributes(inherit);
}
public override bool IsDefined(Type attributeType, bool inherit)
{
return _baseType.IsDefined(attributeType, inherit);
}
public override string Name
{
get { return _baseType.Name; }
}
}
/// <summary>
/// 继承抽象类 PropertyInfo,以实现自定仪的 PropertyInfo
/// </summary>
private class CustomPropertyInfoHelper : PropertyInfo
{
public string _name;
public Type _type;
public List<Attribute> _attributes = new List<Attribute>();
public CustomPropertyInfoHelper(string name, Type type)
{
_name = name;
_type = type;
}
public CustomPropertyInfoHelper(string name, Type type, List<Attribute> attributes)
{
_name = name;
_type = type;
_attributes = attributes;
}
public override PropertyAttributes Attributes
{
get { throw new NotImplementedException(); }
}
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override MethodInfo[] GetAccessors(bool nonPublic)
{
throw new NotImplementedException();
}
public override MethodInfo GetGetMethod(bool nonPublic)
{
throw new NotImplementedException();
}
public override ParameterInfo[] GetIndexParameters()
{
throw new NotImplementedException();
}
public override MethodInfo GetSetMethod(bool nonPublic)
{
throw new NotImplementedException();
}
public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, System.Globalization.CultureInfo culture)
{
return obj.GetType().GetMethod("GetPropertyValue").Invoke(obj, new[] { _name });
}
public override Type PropertyType
{
get { return _type; }
}
public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, System.Globalization.CultureInfo culture)
{
obj.GetType().GetMethod("SetPropertyValue").Invoke(obj, new[] { _name, value });
}
public override Type DeclaringType
{
get { throw new NotImplementedException(); }
}
public override object[] GetCustomAttributes(Type attributeType, bool inherit)
{
var attrs = from a in _attributes where a.GetType() == attributeType select a;
return attrs.ToArray();
}
public override object[] GetCustomAttributes(bool inherit)
{
return _attributes.ToArray();
}
public override bool IsDefined(Type attributeType, bool inherit)
{
throw new NotImplementedException();
}
public override string Name
{
get { return _name; }
}
public override Type ReflectedType
{
get { throw new NotImplementedException(); }
}
internal List<Attribute> CustomAttributesInternal
{
get { return _attributes; }
}
}
}
}
OK
[源码下载]