Chinaunix首页 | 论坛 | 博客
  • 博客访问: 49237
  • 博文数量: 21
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 190
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-24 15:25
文章分类

全部博文(21)

文章存档

2013年(21)

我的朋友

分类: C#/.net

2013-07-23 11:51:33

C# – Type.IsAssignableFrom.

Topic: C# – CoerceValueCallback

标题: C# – CoerceValueCallback合并、替换元数据值

像在中说道

As in the references page

 

属性元数据的该回调方法一般不是公有方法,所以, 这个值通常情况下对于只是使用dependency property元数据的条件下不是很重要。使用该属性的一个可能原因是元数据的子类可以应用他们合并逻辑,如果基类和重载类有这个CoerceCallback属性。一般的,CoerceValueCallback的默认合并逻辑是替换。

The callbacks in property metadata are not typically public members on the containing type, so the value of this property is not important for most scenarios that just consume an existing dependency property's metadata. One reason this property is exposed is so that metadata subclasses can perform their desired merge logic if both base metadata and overriding/adding metadata specify a . However, the default merge logic for aCoerceValueCallback is to replace the previous one.

在一文中:

And in the

 

调用时间可以是属性系统的任何时间或者是DependencyObjects上显示的调用CoerceValue 方法,调用时,该属性的标识符作为参数dp的值。

The  for a dependency property is invoked any time that the property system or any other caller calls  on a instance, specifying that property's identifier as the dp.

使用CoerceValueCallback的最大可能原因是当你希望在子类中重载基类并提供一个计算在子类中计算重载的dependency property的值的方法。(比如通过OverrideMetaData(Type, PropertyMetadata)...重载父类中dependency property的值).

The biggest reason that you would use a CoerceValueCallback is that when you try to override a base class and try to provide new method to calculate the value of a dependency property that the derived classes override from the base class (e.g. with the OverrideMetaData(Type, PropertyMetadata)...

你可以按照如下的情况,设置CoerceValueCallback值;

You can set the instance of CoerceValueCallback on the following conditions.

·         在新类中定义新dependency property, 调用 .

·         当继承一个已有dependency property的基类上继承子类,在该已有的 dependency property上重载元数据(调用 ),

·         在新类上调用, 在已有的dependency property上加入新的元数据


·         Define a new dependency property on a new class, using either signature of , giving the metadata as the typeMetadata value.

·         Override the metadata (call ) for an existing dependency property, when you derive from the class that owns the dependency property.

·         Add an existing dependency property to a new  class, using new metadata, by calling .


为什么我门需要CoerceValueCallback,我们来看一个例子:

Why we should use the CoerceValueCallback? Given an example,

假如我们有一个ListView的继承类,叫做CustomListView,我们把GridViewColumn替换成CustomGridViewColumn,在CustomGridViewColumn中,我们重载该dependency property

We have a ListView derived class, called CustomListView, and we replace the GridViewColumn with CustomGridViewColumn. And in the CustomGridViewColumn, we have the following override

        static CustomGridViewColumn()

        {

            WidthProperty.OverrideMetadata(

                typeof(CustomGridViewColumn),

                new FrameworkPropertyMetadata(WidthProperty.DefaultMetadata.DefaultValue, null, OnCoerceWidthValue));

        }

 

在OnCoerceWithValue方法中,我们可以这么做

And the OnCoerceWithValue function is as follow.

        private static object OnCoerceWidthValue(DependencyObject d, object basevalue)

        {

            var column = d as CustomGridViewColumn;

            if (column == null)

            {

                return basevalue;

            }

 

            var width = (double)basevalue;

 

            if (column.IsFixedSize)

            {

                if (column.FixedWidth > 0)

                {

                    return column.FixedWidth;

                }

            }

 

            width = column.MinWidth >= 0 ? Math.Max(width, column.MinWidth) : width;

            width = column.MaxWidth >= 0 ? Math.Min(width, column.MaxWidth) : width;

 

            if (column.IsFixedSize)

            {

                if (column.FixedWidth < 1 || double.IsNaN(column.FixedWidth))

                {

                    column.FixedWidth = width;

                }

            }

 

            return width;

        }


如你所示例,扩展类定义了如何确定该列宽度的方法。

As you can see, the extended class has its own way of determine the width of a column;


我们还准备了一个例子,该例中,假设我们要写一个名字为Shirt的自定义控件/用户控件,并且当该控件表示的类型没有扣子时,我们提供了该控件扣子类型的默认值。(比如说, ButtonColors.Black – 初始值)。

For another example, suppose that we are writing a UserControl/CustomControl, whose name is Shirt, and we have default value for those kind of Shirt w/ buttons (those Shirt has no buttons, we will set the ButtonColor to ButtonColors.Black -- the starting value).

    public partial class Shirt : UserControl

    {

        #region Dependency Properties

        public static readonly DependencyProperty ButtonColorProperty = DependencyProperty.Register(

            "ButtonColor",

            typeof(ButtonColors),

            typeof(Shirt),

            new FrameworkPropertyMetadata(ButtonColors.White, null, CoerceButtonColor)

            );

 

        private static object CoerceButtonColor(DependencyObject d, object basevalue)

        {

            ShirtTypes newShirtType = (d as Shirt).ShirtType;

            if (newShirtType == ShirtTypes.Dress || newShirtType == ShirtTypes.Bowling)

            {

                return ButtonColors.Black;

            }

            return ButtonColors.None;

        }

 

        public ButtonColors ButtonColor

        {

            get { return (ButtonColors)GetValue(ButtonColorProperty); }

            set { SetValue(ButtonColorProperty, value); }

        }

 

 

        public static readonly DependencyProperty ShirtTypeProperty = DependencyProperty.Register(

            "ShirtType",

            typeof(ShirtTypes),

            typeof(Shirt),

            new FrameworkPropertyMetadata(ShirtTypes.Polo, null)

            );

 

        public ShirtTypes ShirtType

        {

            get { return (ShirtTypes)GetValue(ShirtTypeProperty); }

            set { SetValue(ShirtTypeProperty, value); }

        }

 

        #endregion Dependency Properties

 

 

        #region Properties

        #endregion Properties

 

 

        #region Constructors

        public Shirt()

        {

            InitializeComponent();

 

            ButtonColor = ButtonColors.White;

            ShirtType = ShirtTypes.Polo;

        }

        #endregion Constructors

    }

注意上面的CoerceButtonColor函数名,结果是用Shirt的类型决的。

Note the code on name CoerceButtonColor,fthe resulting value is determined by the type of Shirt the control represent.


             xmlns=""

             xmlns:x=""

             xmlns:local="clr-namespace:DemoCoerceValueCallback.Converters"

             xmlns:constants="clr-namespace:DemoCoerceValueCallback"

             x:Name="_Shirt"

             >

   

       

   

   

       

           

           

       

       

       

       

 

该例子中用到的其他类型是

The Supporting classes include

 

    public enum ButtonColors

    {

        Black,

        White,

        None,

    }

 

    public enum ShirtTypes

    {

        Dress,

        Bowling,

        Polo,

    }

 

And Converters.

 

    public class ButtonColorConverter : System.Windows.Data.IValueConverter

    {

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

        {

            var buttonColor = (ButtonColors)value;

            var color = Colors.Red;

 

            switch (buttonColor)

            {

                case ButtonColors.Black:

                    color = Colors.Aqua;

                    break;

                case ButtonColors.White:

                    color =  Colors.Beige;

                    break;

                case ButtonColors.None:

                    color = Colors.Blue;

                    break;

                default:

                    color = Colors.Red;

                    break;

            }

            return new SolidColorBrush(color);

        }

 

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

        {

            throw new NotImplementedException();

        }

    }

 

所以总的来说,CoerceValueCallback是一个以元数据方式提供给DependencyProperty的方法,利用它可以让程序员合并(或者是替换)元数据的子类DependencyProperty值。 一般来说你可以在如下三总方法中设置回调 1。在新类中定义新的DependencyProperty;2。OverrideMetadata(Type, ProeprtyMetadata)重载已有DependencyProperty的元数据;3。在新类中加入已有类。

So, in conclusion: CoerceValueCallback is the mean provided as a MetaData to the DependencyProperty which allows developer to merge (or replace, which is the default merge logic) in metadata subclass. Generally you can pass in your own Coerce logic in three conditions, 1. Defining a new dependency property on a new class. 2. Override the metadata for an existing dependency with OverrideMetadata(Type, ProeprtyMetadata) property. 3. Add a existing dependency Property to a new DependencyObject class.

参考:

References


阅读(547) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~