项目开发中遇到一个要求,需要将ComboBox右侧中的小三角箭头给去掉,通过Blend工具“编辑ComboBox的模板副本”得知,这是一个名为"BtnArrow"的Path。但是在CS代码中,是无法引用到这个控件的。
解决办法:重新定义一个类,继承自ComboBox,然后重写OnApplyTemplate方法,代码如下
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的可视性。
注:
// // Summary: // 在实例化的 System.Windows.Controls.ControlTemplate 可视化树中检索已命名的元素。 // // Parameters: // childName: // 要查找的元素的名称。 // // Returns: // 模板中的命名元素(如果已找到)。如果在模板中找不到具有名称 childName 的元素,则可能返回 null。 protected DependencyObject GetTemplateChild(string childName);
通过查看GetTemplateChild方法的定义得知,这是一个Protected方法,所以只能在子类中使用,这也就是为什么在常规Xaml.cs文件中无法获取ContentTemplate中命名控件的原因。
剩下的事情就简单了,来测试一把!
xaml文件如下:
<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部分:
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; } } }
运行截图:
按下按钮前
按下按钮后