Silverlight:获取ContentTemplate中的命名控件

2018-01-23 17:10:48 浏览数 (1)

项目开发中遇到一个要求,需要将ComboBox右侧中的小三角箭头给去掉,通过Blend工具“编辑ComboBox的模板副本”得知,这是一个名为"BtnArrow"的Path。但是在CS代码中,是无法引用到这个控件的。

解决办法:重新定义一个类,继承自ComboBox,然后重写OnApplyTemplate方法,代码如下

代码语言:javascript复制
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;

namespace ContentTemplateTest
{
    public class YJMComboBox : ComboBox
    {

        public bool IsShowDropDownArrow
        {
            get { return (bool)GetValue(IsShowDropDownArrowProperty); }
            set { SetValue(IsShowDropDownArrowProperty, value); }
        }

        
        public static readonly DependencyProperty IsShowDropDownArrowProperty =
            DependencyProperty.Register("IsShowDropDownArrow", typeof(bool), typeof(YJMComboBox), new PropertyMetadata(true, OnIsShowDropDownArrowChanged));


        static void OnIsShowDropDownArrowChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            YJMComboBox _yjmCombobox = obj as YJMComboBox;
            if (_yjmCombobox != null)
            {
                if ((bool)args.NewValue)
                {
                    _yjmCombobox._DropDownToggleButton.Visibility = Visibility.Visible;
                }
                else
                {
                    _yjmCombobox._DropDownToggleButton.Visibility = Visibility.Collapsed;
                }
            }
        }

        private Path _DropDownToggleButton = new Path();

        public override void OnApplyTemplate()
        {
            _DropDownToggleButton = GetTemplateChild("BtnArrow") as Path;
            base.OnApplyTemplate();
        }
    }
}

我增加了一个BOOL型的依赖属性IsShowDropDownArrow,并在OnApplyTemplate方法重载时获取了BtnArrow的引用,然后在IsShowDropDownArrow属性变化时,修改了BtnArrow的可视性。

注:

代码语言:javascript复制
        //
        // Summary:
        //     在实例化的 System.Windows.Controls.ControlTemplate 可视化树中检索已命名的元素。
        //
        // Parameters:
        //   childName:
        //     要查找的元素的名称。
        //
        // Returns:
        //     模板中的命名元素(如果已找到)。如果在模板中找不到具有名称 childName 的元素,则可能返回 null。
        protected DependencyObject GetTemplateChild(string childName);

  通过查看GetTemplateChild方法的定义得知,这是一个Protected方法,所以只能在子类中使用,这也就是为什么在常规Xaml.cs文件中无法获取ContentTemplate中命名控件的原因。

剩下的事情就简单了,来测试一把!

xaml文件如下:

代码语言:javascript复制
<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:System="clr-namespace:System;assembly=mscorlib" x:Class="ContentTemplateTest.MainPage"
    mc:Ignorable="d"
    xmlns:local="clr-namespace:ContentTemplateTest"
    d:DesignHeight="300" d:DesignWidth="400">



    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
            <local:YJMComboBox HorizontalAlignment="Center" VerticalAlignment="Center" Width="100" x:Name="cbo">
              
            </local:YJMComboBox>
            <Button Content="Test" HorizontalAlignment="Center" VerticalAlignment="Top" Click="Button_Click" Margin="10,0,0,0"></Button>
        </StackPanel>
    </Grid>
</UserControl>

 Xaml.cs部分:

代码语言:javascript复制
using System.Windows;
using System.Windows.Controls;

namespace ContentTemplateTest
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();            
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.cbo.IsShowDropDownArrow = !this.cbo.IsShowDropDownArrow;
        }
    }
}

运行截图:

按下按钮前

按下按钮后

0 人点赞