none
实现自定义控件时,如何将属性映射到背景线性渐变的渐变点 RRS feed

  • 问题

  • 需要这样一个控件:
    • 在Border中有一个TextBlock
    • 控件提供Text属性,用于在屏幕上显示
    • 控件提供Percentage属性,用于在Text背后显示颜色条以表示百分比

    cs文件在(有代码着色,行号方便阅读) http://paste.pocoo.org/show/186949/

    xaml文件在 http://paste.pocoo.org/show/186950/

    在各个文件有简单的注释,我也不理解silverlight自定义控件的整体结构,找到的资料都是四处分散,或者太基础的
    2010年3月8日 11:12

答案

  • ri,这个论坛怎么这样啊,纯文本格式都瞎折腾
    -----------------------------------------
    谢谢关注
    
    我后来发现我把基础的概念搞错了,因为之前是学Java的,所以认为只要把文件放到相关的路径下就可以了.
    
    最后发现错了,需要在项目上添加新项时选择模板化控件,然后会生成cs文件和Themes\Generic.xaml, 界面需要写在Generic.xaml中, 格式和我上面写的一样
    
    而我之前一直是新建用户控件...
    
    
    还有一些额外的心得希望对其他人有用:
    
    *. 我发现实现的模板化控件,如果有自定义属性,那么在初始化时会先调用属性的set {SetValue(PercentageProperty, value);}, 然后会调用PercentageProperty在注册时new PropertyMetadata()中定义的委托
    
    但是在这个时候,控件还不具有界面-_-b,要在override OnApplyTemplate之后才有界面
    
    所以就有了Silverlight Toolkits中这样的代码
            private static void OnHasCloseButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {   
                ChildWindow cw = (ChildWindow)d;
    
                if (cw.CloseButton != null)  /// 这个方法会在OnApplyTemplate()之前调用,这个时候cw.CloseButton这个UIElement还是null
                {
                    if ((bool)e.NewValue)
                    {
                        cw.CloseButton.Visibility = Visibility.Visible;
                    }
                    else
                    {
                        cw.CloseButton.Visibility = Visibility.Collapsed;
                    }
                }
            }
    然后在OnApplyTemplate中
                this.CloseButton = GetTemplateChild(PART_CloseButton) as ButtonBase;
    
                if (this.CloseButton != null)
                {
                    if (this.HasCloseButton)
                    {
                        this.CloseButton.Visibility = Visibility.Visible;
                    }
                    else
                    {
                        this.CloseButton.Visibility = Visibility.Collapsed;
                    }
                }
    
    貌似将自己的代码重复了,不知道这种情况有什么别的优美些的处理办法,上面2段代码在 http://silverlight.codeplex.com/sourcecontrol/network/Show?projectName=Silverlight&changeSetId=35261#636495
    
    
    *. 在构造方法中应该有
    this.DefaultStyleKey = typeof(MyCustomControl);
    指定默认样式,这样就会使用Generic.xaml中的样式
    
    *. Generic.xaml中是不是不能使用ResourceDictionary.MergedDictionaries,如果不能的话,哪有什么工具能合并多个xaml到Generic.xaml
    
    自定义属性会影响到控件中的什么UIElement的代码需要自己写,能使用TemplateBinding的机会并不总是有

    额外要注意 必须在类中使用TemplatePart标记声明必须的UIElement和其类型, 才能在OnApplyTemplate中使用GetTemplateChild()得到这个UIElement

    牢骚,为什么那么多基础控件都不允许继承啊,TextBlock,Border,如果我想让自定义控件支持TextBlock Border的某些专有属性,有什么比较简洁的方法?

    感觉上实现自定义控件时框架代码太繁琐了, 但是从最终设计上看这些又是必须的...
    2010年3月12日 3:27

全部回复

  • 你好, 
       
         我吧你的代码放到vs里是可以运行的。
     
         不过我加上了override OnApplyTemplate方法。 
     
        你可以试试看
    2010年3月10日 8:43
  • ri,这个论坛怎么这样啊,纯文本格式都瞎折腾
    -----------------------------------------
    谢谢关注
    
    我后来发现我把基础的概念搞错了,因为之前是学Java的,所以认为只要把文件放到相关的路径下就可以了.
    
    最后发现错了,需要在项目上添加新项时选择模板化控件,然后会生成cs文件和Themes\Generic.xaml, 界面需要写在Generic.xaml中, 格式和我上面写的一样
    
    而我之前一直是新建用户控件...
    
    
    还有一些额外的心得希望对其他人有用:
    
    *. 我发现实现的模板化控件,如果有自定义属性,那么在初始化时会先调用属性的set {SetValue(PercentageProperty, value);}, 然后会调用PercentageProperty在注册时new PropertyMetadata()中定义的委托
    
    但是在这个时候,控件还不具有界面-_-b,要在override OnApplyTemplate之后才有界面
    
    所以就有了Silverlight Toolkits中这样的代码
            private static void OnHasCloseButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {   
                ChildWindow cw = (ChildWindow)d;
    
                if (cw.CloseButton != null)  /// 这个方法会在OnApplyTemplate()之前调用,这个时候cw.CloseButton这个UIElement还是null
                {
                    if ((bool)e.NewValue)
                    {
                        cw.CloseButton.Visibility = Visibility.Visible;
                    }
                    else
                    {
                        cw.CloseButton.Visibility = Visibility.Collapsed;
                    }
                }
            }
    然后在OnApplyTemplate中
                this.CloseButton = GetTemplateChild(PART_CloseButton) as ButtonBase;
    
                if (this.CloseButton != null)
                {
                    if (this.HasCloseButton)
                    {
                        this.CloseButton.Visibility = Visibility.Visible;
                    }
                    else
                    {
                        this.CloseButton.Visibility = Visibility.Collapsed;
                    }
                }
    
    貌似将自己的代码重复了,不知道这种情况有什么别的优美些的处理办法,上面2段代码在 http://silverlight.codeplex.com/sourcecontrol/network/Show?projectName=Silverlight&changeSetId=35261#636495
    
    
    *. 在构造方法中应该有
    this.DefaultStyleKey = typeof(MyCustomControl);
    指定默认样式,这样就会使用Generic.xaml中的样式
    
    *. Generic.xaml中是不是不能使用ResourceDictionary.MergedDictionaries,如果不能的话,哪有什么工具能合并多个xaml到Generic.xaml
    
    自定义属性会影响到控件中的什么UIElement的代码需要自己写,能使用TemplateBinding的机会并不总是有

    额外要注意 必须在类中使用TemplatePart标记声明必须的UIElement和其类型, 才能在OnApplyTemplate中使用GetTemplateChild()得到这个UIElement

    牢骚,为什么那么多基础控件都不允许继承啊,TextBlock,Border,如果我想让自定义控件支持TextBlock Border的某些专有属性,有什么比较简洁的方法?

    感觉上实现自定义控件时框架代码太繁琐了, 但是从最终设计上看这些又是必须的...
    2010年3月12日 3:27