【WP8】自定义控件

1、测量和安排布局:MeasureOverride, ArrangeOverride

  

    //测量(传入控件的可用大小)
    protected override Size MeasureOverride(Size availableSize)
    {
        //遍历所有子空间
        foreach (UIElement child in InternalChildren)
        {
            //计算控件可用大小,调用子控件的MeasureOverride方法
            child.Measure(availableSize);
            //获得控件大小
            //child.DesiredSize
        }

        //返回给ArrangeOverride调用
        return availableSize;
    }
    
    //安排布局
    protected override Size ArrangeOverride(Size finalSize)
    {
        double x = 0;
        foreach (UIElement child in InternalChildren)
        {
            //安排控件实际渲染位置,通过 DesiredSize获得控件需要的大小
            child.Arrange(new Rect(new Point(x, 0), child.DesiredSize));
            x += child.DesiredSize.Width;
        }
        //返回控件实际布局大小(在父控件通过DesiredSize获得)
        return finalSize;
    }

 

2、依赖属性

//注册依赖属性
    public static DependencyProperty TextProperty = DependencyProperty.Register("MyText",
                                       typeof(string),
                                       typeof(MySilverButton),
                                       new PropertyMetadata("默认属性值", OnTextPropertyChanged));

    //依赖属性对应的控件属性
    public string MyText
    {
        get { return (string) GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
    
    //依赖属性回掉函数(static)
    private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //这里MySilverButton是控件类名
        var mySilverButton = d as MySilverButton;
        if (mySilverButton!=null)
            mySilverButton.OnTextPropertyChanged(e);
    }
    
    //属性变化回掉(通过静态函数调用,也可以在静态函数里写)
    private void OnTextPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        var bgTextBlock = GetTemplateChild("ButtonCaption") as TextBlock;
        if (bgTextBlock != null) bgTextBlock.Text = e.NewValue as string;
    }

 

  在xaml中定义Template时,可以通过{TemplateBinding MyText}绑定依赖属性

3、在模板加载完成后注册事件和一些初始化操作
  public override void OnApplyTemplate()

4、获取子控件和资源(定义在Generic.xaml)

    //获取根控件
    var root = (FrameworkElement)GetTemplateChild("RootElement");
    //获取控件资源
    var enter = (Storyboard)root.Resources[MouseEnterAnimation];

 

5、元数据

  在控件的定义加上TemplatePart特性,该特性不是必须的,只是一种契约,推荐这样设计控件

  意思是告诉要来写ControlTemplate的用户,你的ControlTemplate中需要有一个x:Name为“LayoutRoot” , 类型为 Panel 的元素 , 因为逻辑部分对这些东西进行了引用,它们将对控件的默认行为起着关键作用, 可以理解为这个控件的最基本元素,是实现默认行为的最小集合,主要是给用户看的

    [TemplatePart(Name = "LayoutRoot", Type = typeof (Panel))]
    [TemplateVisualState(GroupName = "HoverStates", Name = "MouseOver")]
    [TemplateVisualState(GroupName = "HoverStates", Name = "Normal")]
    public class MyControl : Control

 

6、视图状态

//一般在ControlTemplate中的Border控件内部定义

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="HoverStates">
            <VisualState x:Name="MouseOver">
                <Storyboard>
                    <ColorAnimation
                        Storyboard.TargetName="BackgroundElement"
                        Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)"
                        To="Yellow" Duration="0:0:.5" />
                </Storyboard>
            </VisualState>
            <VisualState x:Name="Normal">
                <Storyboard>
                    <ColorAnimation
                        Storyboard.TargetName="BackgroundElement"
                        Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)"
                        To="Transparent" Duration="0:0:.5" />
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

 

  //在视图中定义不同视图状态的过度动画逻辑

  在cs中改变视图状态(this表示该控件)
  VisualStateManager.GoToState(this, "MouseOver", useTransitions);

参考链接
1、WPF MeasureOverride And ArrangeOverride
  http://www.cnblogs.com/dingli/archive/2011/04/22/2024786.html
2、用户自定义控件详解
  http://blog.csdn.net/mr_raptor/article/details/7251942

 

 

 

 

posted @ 2014-02-13 14:55  bomo  阅读(1591)  评论(0编辑  收藏  举报