WF,WPF,Silverlight的DependencyProperty 附加属性
注意,是DependencyProperty 附加属性,而不是绑定属性
例子: https://files.cnblogs.com/foundation/Projects.rar
首先看一个假设,
在不修改一个类的前提下,如何扩展一个类的成员(继承也不可以)
这在传统的OO设计中是无法完成的,但在NET3.0(C#3.0,VB.NET9.0)中提供了扩展方法开实现这一功能
看下例:
场景:我经常要用得到数字除2的结果,如何方便的实现
class Program { static void Main(string[] args) { double v1 = 123; double p1 = v1.zzzzz(); System.Console.WriteLine(p1);
//-- double p2=(1234567890.123).zzzzz(); System.Console.WriteLine(p2); } }
static class myExtension { public static double zzzzz(this double d) { return d/2 ; } } |
这就是扩展方法,在不修改的结构的情况下,为[ double ]添加了[zzzzz]这个方法
linq 用的就是这种方式
方法可以这样做,那属性哪?
升级一下需求,我想一个对象在一个环境中自动多出某几个属性,在另外一个环境中又自动多出另外几个属性
如何做,
先看一下Silverlight
场景:提供一个容器,容器分两排,放入容器内的件意控件都可设置附加属性[myTag]的属性,[myTag]属性设为[a]的在左边,设为[b]的在右边
容器
public class wxdPanel : StackPanel { StackPanel p1 = new StackPanel(); StackPanel p2 = new StackPanel(); public wxdPanel() : base() { p1.Width = 200; p2.Width = 200; p1.Background = new System.Windows.Media.SolidColorBrush(new Color() { R = 0, G=255, B=0 , A=255}); p2.Background = new System.Windows.Media.SolidColorBrush(new Color() { R = 0, G = 0, B = 255, A = 255 }); this.Orientation = Orientation.Horizontal; this.Children.Add(p1); this.Children.Add(p2); this.Loaded += new RoutedEventHandler(wxdPanel_Loaded); } List<FrameworkElement> list = new List<FrameworkElement>(); void wxdPanel_Loaded(object sender, RoutedEventArgs e) { foreach (var p in this.Children) { if (p is StackPanel) { } else { list.Add((FrameworkElement)p); } }
foreach (var v in list) {
this.Children.Remove(v);
if (wxdPanel.GetmyTag(v) == "a") { p1.Children.Add(v); } if (wxdPanel.GetmyTag(v) == "b") { p2.Children.Add(v); } } } public static string GetmyTag(DependencyObject obj) { return (string )obj.GetValue(myTagProperty); } public static void SetmyTag(DependencyObject obj, string value) { obj.SetValue(myTagProperty, value); } public static readonly DependencyProperty myTagProperty = DependencyProperty.RegisterAttached("myTag", typeof(string ), typeof(wxdPanel),new PropertyMetadata(""));
} |
使用
<UserControl x:Class="SilverlightApplication1.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300" xmlns:mytype="clr-namespace:SilverlightApplication1"> <mytype:wxdPanel > <Button Name="Button1" mytype:wxdPanel.myTag="a" Height="53" Width="75" Content="Button1" /> <TextBox Name="TextBox1" mytype:wxdPanel.myTag="a" Height="23" Width="120" Text="TextBox1"/> <Button Name="Button2" mytype:wxdPanel.myTag="a" Height="53" Width="75" Content="Button2" /> <TextBox Name="TextBox2" mytype:wxdPanel.myTag="b" Height="23" Width="120" Text="TextBox2" /> <Button Name="Button3" mytype:wxdPanel.myTag="a" Height="53" Width="75" Content="Button3" /> <TextBox Name="TextBox3" mytype:wxdPanel.myTag="b" Height="23" Width="120" Text="TextBox3"/> </mytype:wxdPanel>
</UserControl> |
效果
WPF的实现
与Silverlight 相同
再看一下WF的实现
场景:提供一个容器,放入容器内的件意Activity会多出一个明为[myTag]的属性,[myTag]属性设为[a]的执行,设为[b]的不执行
先创建这个容器Activity
[Designer(typeof(myDesigner), typeof(IDesigner))] public partial class myContainer : System.Workflow.ComponentModel.CompositeActivity { //- public static string GetmyTag(object obj) { DependencyObject dObject = obj as DependencyObject; object value = dObject.GetValue(myTagProperty); return value.ToString(); } public static void SetmyTag(object obj, string value) { DependencyObject dObject = obj as DependencyObject; dObject.SetValue(myTagProperty, value); } public static readonly DependencyProperty myTagProperty = DependencyProperty.RegisterAttached("myTag", typeof(string), typeof(myContainer), new PropertyMetadata("")); public static string GetleftValue(object obj) { DependencyObject dObject = obj as DependencyObject; object value = dObject.GetValue(leftValueProperty); return value.ToString(); } public static void SetleftValue(object obj, object value) { DependencyObject dObject = obj as DependencyObject; dObject.SetValue(leftValueProperty, value); } public static readonly DependencyProperty leftValueProperty = DependencyProperty.RegisterAttached("leftValue", typeof(string), typeof(myContainer), new PropertyMetadata("")); int n = 0; protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) { n = this.EnabledActivities.Count;
if (n == 0) { return ActivityExecutionStatus.Closed; }
foreach (Activity activity in this.EnabledActivities) { n = n - 1; string l = myContainer.GetmyTag(activity);
if (l == "a") { activity.Closed += new EventHandler<ActivityExecutionStatusChangedEventArgs>(activity_Closed); executionContext.ExecuteActivity(activity); } }
return ActivityExecutionStatus.Executing; }
void activity_Closed(object sender, ActivityExecutionStatusChangedEventArgs e) { ActivityExecutionContext executionContext = sender as ActivityExecutionContext; if (n == 0) { executionContext.CloseActivity(); } } }
[ProvideProperty("myTag", typeof(Activity))] public class myExtenderProvider : IExtenderProvider { public bool CanExtend(object extendee) { return (((extendee != this) && (extendee is Activity)) && (((Activity)extendee).Parent is myContainer)); } //- public string GetmyTag(Activity activity) { if (activity.Parent is myContainer) { return activity.GetValue(myContainer.myTagProperty).ToString(); } return null; } public void SetmyTag(Activity activity, string value) { if (activity.Parent is myContainer) { activity.SetValue(myContainer.myTagProperty, value); } } }
public class myDesigner : SequenceDesigner { protected override void Initialize(Activity activity) { base.Initialize(activity); IExtenderListService service = (IExtenderListService)base.GetService(typeof(IExtenderListService)); if (service != null) { bool tag = false; foreach (IExtenderProvider provider in service.GetExtenderProviders()) { if (provider.GetType() == typeof(myExtenderProvider)) { tag = true; } } if (!tag) { IExtenderProviderService tempService = (IExtenderProviderService)base.GetService(typeof(IExtenderProviderService)); if (tempService != null) { tempService.AddExtenderProvider(new myExtenderProvider()); } } } } } |
然后设计工作流
运行结果