WpfMarkupExtension学习笔记

MarkupExtension:msdn上定义:

为可以由 .NET Framework XAML 服务及其 XAML 读取器和 XAML 编写器支持的 XAML 标记扩展实现提供基类。

个人使用下来的感觉有点类似于附加属性,但是附加属性是用来定义的赋值的,而该扩展类可以用来作为变量绑定附加属性或者依赖属性。

每个继承MarkupExtension的类都需要override一个方法:

public override object ProvideValue(
                               IServiceProvider serviceProvider)

 

当中参数IServiceProvider serviceProvider可以提供一个object GetService(Type serviceType);方法:

具体使用:

 

 

 IProvideValueTarget ipvt =
                (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));

DependencyObject targetObject = ipvt.TargetObject as DependencyObject;
DependencyProperty dp = ipvt.TargetProperty as DependencyProperty;

 

通过该方法,可以获取绑定的控件,以及绑定的属性。

 

同时可以定义多个属性,以及对应的构造函数,配合设计模型需要。

public MaxValueExtensionFull(object value1, object value2)
        {
            Value1 = value1;
            Value2 = value2;
        }

        [ConstructorArgument("value1")]
        public object Value1 { get; set; }

        [ConstructorArgument("value2")]
        public object Value2 { get; set; }

好了定义了这么多,为的是什么呢?接下来可以为我们的扩展xaml添加逻辑内容了:

private object GetMaxValue()
        {
            if (Value1 is IComparable && Value1 is IComparable)
            {
                if (((IComparable)Value1).CompareTo(Value2) >= 0)
                    return Value1;
                else
                    return Value2;
            }
            else
            {
                // use val1
                return Value1;
            }
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (serviceProvider == null)
                return null;

            // get the target of the extension from the IServiceProvider interface
            IProvideValueTarget ipvt =
                (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));

            DependencyObject targetObject = ipvt.TargetObject as DependencyObject;

            object val = GetMaxValue();

            if (ipvt.TargetProperty is DependencyProperty)
            {
                // target property is a DP
                DependencyProperty dp = ipvt.TargetProperty as DependencyProperty;

                if (val is IConvertible)
                {
                    val = Convert.ChangeType(val, dp.PropertyType);
                }
            }
            else
            {
                // target property is not a DP, it's PropertyInfo instead.
                PropertyInfo info = ipvt.TargetProperty as PropertyInfo;

                if (val is IConvertible)
                {
                    val = Convert.ChangeType(val, info.PropertyType);
                }
            }

            return val;
        }

刚开始这么写扩展,觉得有些多余,我可以在控件上加依赖属性,加converter转换,一样可以绑定,但是这样子的话一个控件就要一堆属性和converter,代码冗余。

而使用扩展后,我只需要定义一个Extension,那么就可以在所有控件上都使用了。

 

 

 

 

 

posted @ 2013-09-06 14:05  gavin.huang  阅读(361)  评论(0编辑  收藏  举报