Behavior,Trigger,TriggerAction中使用ElementName
来源:互联网 发布:js正则test 编辑:程序博客网 时间:2024/06/05 14:14
Behavior,Trigger,TriggerAction属于元素的附加属性,并不在可视化树中,当我们在绑定的时候需要使用ElementName指定数据源的时候,ElementName是不起作用的。因为使用ElementName属性本身的元素需要在可视化树中。 我说明一下IsLoaded函数,其他的函数看注释。FindName是有使用条件的,对象本身必须处于可是化树中才可通过这个函数找到指定的对象,IsLoaded就是用来判断这个的,具体如何判断看我后面的代码。 下面是施行邦定的关键代码: 邦定的过程在CreateRelayBinding函数中。 使用起来很简单,比如我们有一个NavigateAction,用来导航,里面有一个Parameter,用来向下一个页面传递参数, 导航前界面:
在FrameworkElement中有一个FindName函数,通过这个函数我们可以找到当前 XAML 命名空间中指定的对象。而Binding中的ElementName属性实现也是间接的调用到这个函数。 Behavior,Trigger,TriggerAction中都保存有被附加的对象,通过这个对象和FindName再加上反射,我们就可以实现ElementName。
Behavior,Trigger,TriggerAction中并没有ElementName函数,但可以通过调用附加对象的ElementName来实现这个功能。我选择使用接口来扩展这样的功能。
首先定义通用接口:
interface IElementBinding { /// <summary> /// 附加对象改变时触发的事件 /// </summary> event EventHandler AssociatedObjectChanged;//附加对象改变时触发的事件 /// <summary> /// 附加对象是否在可视化树中 /// </summary> /// <returns></returns> bool IsLoaded(); /// <summary> /// 查找元素 /// </summary> /// <param name="name"></param> /// <returns></returns> object FindName(string name); /// <summary> /// 获取继承接口的对象 /// </summary> /// <returns></returns> DependencyObject GetDependencyObject(); }
定义完接口然后需要一个结构来指定邦定中需要用到的属性:
public class BindingProperties { /// <summary> /// 被附加源中需要绑定的属性名称 /// </summary> public string SourceProperty { get; set; } /// <summary> /// 需要绑定控件的名称 /// </summary> public string ElementName { get; set; } /// <summary> /// 需要绑定控件中的目标属性 /// </summary> public string TargetProperty { get; set; } /// <summary> /// 转换器 /// </summary> public IValueConverter Converter { get; set; } }
public class ElementBinding { public static BindingProperties GetBinding(DependencyObject obj) { if (obj == null) return null; return obj.GetValue(BindingProperty) as BindingProperties; } public static void SetBinding(DependencyObject obj, BindingProperties value) { obj.SetValue(BindingProperty, value); } public static readonly DependencyProperty BindingProperty = DependencyProperty.RegisterAttached("Binding", typeof(BindingProperties), typeof(ElementBinding), new PropertyMetadata(null, new PropertyChangedCallback(ElementBinding.OnBinding))); private static void OnBinding(DependencyObject depObj, DependencyPropertyChangedEventArgs e) { var Interactivity = depObj as IElementBinding; if (Interactivity == null) return; if (Interactivity.IsLoaded()) { CreateRelayBinding(Interactivity, GetBinding(Interactivity.GetDependencyObject())); } else { Interactivity.AssociatedObjectChanged += Interactivity_AssociatedObjectChanged; } } static void Interactivity_AssociatedObjectChanged(object sender, EventArgs e) { IElementBinding sourceElement = sender as IElementBinding; BindingProperties bindingProperties = GetBinding(sourceElement.GetDependencyObject()); CreateRelayBinding(sourceElement, bindingProperties); } private static void CreateRelayBinding(IElementBinding sourceElement, BindingProperties bindingProperties) { if (sourceElement == null || bindingProperties == null) return; //获取被绑定源 var source=sourceElement.GetDependencyObject(); if (source == null) return; //查找目标对象 DependencyObject targetElement = sourceElement.FindName(bindingProperties.ElementName) as DependencyObject; if (targetElement == null) return; //通过反射找到被绑定源中需要被绑定的附加属性 var sourceDependencyPropertyField = source.GetType().GetField(bindingProperties.SourceProperty + "Property", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); if (sourceDependencyPropertyField == null) return; DependencyProperty sourceDependencyProperty = sourceDependencyPropertyField.GetValue(null) as DependencyProperty; Binding binding = new Binding(); binding.Source = targetElement; binding.Path = new PropertyPath(bindingProperties.TargetProperty); binding.Converter = bindingProperties.Converter; //绑定 BindingOperations.SetBinding(source, sourceDependencyProperty, binding); } public static bool IsElementLoaded(FrameworkElement element) { if (element == null) return false; UIElement rootVisual = Application.Current.RootVisual; DependencyObject parent = element.Parent; if (parent == null) { parent = System.Windows.Media.VisualTreeHelper.GetParent(element); } return parent != null || (rootVisual != null && element == rootVisual); } }
邦定流程好了以后可以开始对Behavior,Trigger,TriggerAction进行改造了。邦定中TriggerAction用的比较多,我就
以这个为例子,Behavior和Trigger自行扩展。
首先自己定义一个TriggerAction基类,所有自定义的TriggerAction都从这个基类继承,然后再里面实现IElementBinding的所有接口。注意:不实现IElementBinding接口是无法使用ElementBinding类的。
public abstract class CustomTriggerActionBase : TriggerAction<FrameworkElement>, IElementBinding { public event EventHandler AssociatedObjectChanged; protected override void OnAttached() { base.OnAttached(); if (ElementBinding.IsElementLoaded(this.AssociatedObject) && AssociatedObjectChanged != null) AssociatedObjectChanged(this, new EventArgs()); else if (this.AssociatedObject != null) this.AssociatedObject.Loaded += AssociatedObject_Loaded; } protected override void OnDetaching() { base.OnDetaching(); this.AssociatedObject.Loaded -= AssociatedObject_Loaded; } void AssociatedObject_Loaded(object sender, RoutedEventArgs e) { if (AssociatedObjectChanged != null) AssociatedObjectChanged(this, new EventArgs()); } public bool IsLoaded() { return ElementBinding.IsElementLoaded(this.AssociatedObject); } public object FindName(string name) { return this.AssociatedObject == null ? null : this.AssociatedObject.FindName(name); } public DependencyObject GetDependencyObject() { return this; } }
使用时这样写:
<Button Content="To Page1" Width="200" Height="80" > <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <local:NavigateAction NavigateName="/Page1.xaml"> <local:ElementBinding.Binding> <local:BindingProperties SourceProperty="Parameter" ElementName="ParameterText" TargetProperty="Text"/> </local:ElementBinding.Binding> </local:NavigateAction> </i:EventTrigger> </i:Interaction.Triggers> </Button>
导航后的界面:
示例代码:
ElementBindingText.zip
- Behavior,Trigger,TriggerAction中使用ElementName
- Behavior,Trigger,TriggerAction深度解析
- Behavior<T>和TriggerAction<T>的使用和区别
- jQuery中 trigger() 使用心得
- jQuery中 trigger() 使用心得
- CoordinatorLayout中Behavior介绍与简单使用
- jquery中使用trigger()方法模拟事件
- jQuery中 trigger() & bind() 使用心得
- trigger使用
- 在Joomla!中怎样使用日历部分behavior.calendar 【转】
- 在Joomla!中使用behavior.tree参考 【转】
- CSS中behavior属性语法的使用介绍
- yii2控制器中附加行为behavior()方法使用
- Silverlight - Attached Behavior又一例 可复用的Storyboard Trigger
- CSS中behavior属性
- CoordinatorLayout之Behavior使用
- SQL Server2000 ,在trigger中使用DB link
- SQL Server中trigger和变量的使用笔记
- 类成员的反射,暴力反射,应用实例
- struts2中<s:textfield默认值使用session中的属性值的写法
- 扫描目录下所有文件
- 说产品研发
- JS中变量名作为if条件的真/假
- Behavior,Trigger,TriggerAction中使用ElementName
- 由UIImageView中的UIButton不响应事件引发的
- Oracle体系结构回顾
- 数据标签
- errno含义
- dig
- Unity3D如何区分平台类型
- C++笔记(1)explicit构造函数
- C++ Socket封装