WPF架构关键技术剖析(3)--做自己的交互Action(2)

下面我们利用附加属性,将我们准备好的Action集合能作为附加属性出现在xaml中:

1)附加属性类:

/// <summary>
    /// 附加属性定义类,注意必须是静态的,这有点类似于给类增加扩展方法。
    /// </summary>
    public static class WPFTestDettach
    {
       /// <summary>
       /// 注册附加属性。
       /// </summary>
       public static readonly DependencyProperty MyObjectsProperty =
           DependencyProperty.RegisterAttached("MyObjects", typeof(MyActionCollection), typeof(WPFTestDettach),
           new PropertyMetadata(null,(dobj,darg)=>{
              
              //一般情况下这里可以不要。附加属性的目的是切入,而不会关心其属性的变化。
           }));
       /// <summary>
       /// 这个方法是必须的,命名也有规则MyObjects =》 MyObjectsProperty = GetMyObjects。
       /// 便于解释分析器获取该方法.
       /// </summary>
       /// <param name="obj"></param>
       /// <returns></returns>
       public static MyActionCollection GetMyObjects(DependencyObject obj)
        {
            MyActionCollection theC = (MyActionCollection)(obj.GetValue(MyObjectsProperty));
            if (theC == null)
            {
                theC = new MyActionCollection();
                obj.SetValue(MyObjectsProperty, theC);
            }
            theC.Obj = obj;
            return theC;
        }
        //设置方法类似,不过这里没什么用处,所以从略.
    }

2)定义好了附加属性,就可以用了,如何用,我们暂且不管,先看看,我们如何达到我们在前面一篇所提到的目的,这里我们实现一个具体的Action

/// <summary>
    /// 具体的Action应用,面向TreeView类,可以截获事件,并执行相应的方法.
    /// </summary>
    public class MyActionTest : MyAction<TreeView>
    {
        /// <summary>
        /// 挂接事件的地方,切入点.
        /// </summary>
        public override void OnAttached()
        {
            base.OnAttached();
            //利用反射可以获取到对象的事件信息,并动态设置连接
            //这里因为只是测试,所以简化。
            switch (EventName)
            {
                case "SelectedItemChanged":
                    this.WObj.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(MyWPF_SelectedItemChanged);
                    break;
            }
           
        }
        /// <summary>
        /// 接挂的地方,清楚事件处理挂接,释放不必要的资源.
        /// </summary>
        public override void OnDetaching()
        {
            base.OnDetaching();
            switch (EventName)
            {
                case "SelectedItemChanged":
                    this.WObj.SelectedItemChanged -= new RoutedPropertyChangedEventHandler<object>(MyWPF_SelectedItemChanged);
                    break;
            }
        }
        /// <summary>
        /// 事件处理的地方。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void MyWPF_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            DoSomething(Params);
        }
        /// <summary>
        /// 公开属性可通过Xaml中设置,EventName 要触发的时间名.
        /// </summary>
        public string EventName { get; set; }
        /// <summary>
        /// 参数字符串
        /// </summary>
        public string Params { get; set; }
        /// <summary>
        /// 目标对象,可以是当前页面的UI元素。当然,你也可以自己规定规则,做的非常复杂。
        /// </summary>
        public string TargetName { get; set; }
        /// <summary>
        /// 目标对象上的方法名,就是你需要执行的,注意对象上的这种方法必须是公共的.
        /// </summary>
        public string MethodName { get; set; }
        /// <summary>
        /// 具体事件处理,这里用到了反射.
        /// </summary>
        /// <param name="PMs"></param>
        public void DoSomething(string PMs)
        {

            object theRootObj = GetRootObject(this.WObj);
            object theTargetObj = null;
            //如果目标元素为空,则取页面root element.
            if (TargetName == "")
            {
                theTargetObj = theRootObj;
            }
            else
            {
                //获取目标UI元素.
                theTargetObj = ((FrameworkElement)theRootObj).FindName(TargetName);
            }
            //获取目标方法并调用. 
            MethodInfo theMI = theTargetObj.GetType().GetMethod(MethodName);
            if (theMI != null)
            {
                theMI.Invoke(theTargetObj,new object[]{PMs});
            }

        }
        /// <summary>
        /// 一个自定义的辅助函数,用于获取页面的根结点,这样可以查找本页的UI元素.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private FrameworkElement GetRootObject(FrameworkElement obj)
        {
            if (obj.Parent != null && obj.Parent is FrameworkElement)
            {
                return GetRootObject((FrameworkElement)(obj.Parent));
            }
            return obj;
        }
    }

做好了准备,下面我们就可以应用了.....待续

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值