简体   繁体   English

WPF ComboBox以编程方式隐藏(禁用)DropDown按钮

[英]WPF ComboBox Hide (Disable) DropDown Button Programmatically

I would like to know how to disable ComboBox DropDown Button Programmatically. 我想知道如何以编程方式禁用ComboBox DropDown按钮。 I had seen many similar subjects but all of these have a XAML solution. 我见过许多类似的科目,但所有这些科目都有XAML解决方案。

By the way, if someone know how to disable all ComboBox control design and left visible only item template it can be helpful too. 顺便说一句,如果有人知道如何禁用所有ComboBox控件设计并留下仅可见的项目模板,它也会有所帮助。

UPDATE UPDATE

its my XAML definition 它是我的XAML定义

<ComboBox Name="lang_ComboBox" SelectionChanged="LanguageSelection_ComboBox_SelectionChanged"/>

And there is how i use it: 我有如何使用它:

String text = "dorf";
BitmapImage image = new BitmapImage(new Uri("http://img88.imageshack.us/img88/4351/butchermi4.png"));
lang_ComboBox.Width = 100;
lang_ComboBox.Height = 30;
Grid sp;
for (int i = 0; i < 5; i++)
{
    ColumnDefinition gridCol1 = new ColumnDefinition();
    gridCol1.Width = new GridLength(30.0);
    ColumnDefinition gridCol2 = new ColumnDefinition();
    gridCol2.Width = new GridLength(70.0);
    sp = new Grid()
    {
        Width = 100,
        Height = 30
    };
    Image im = new Image()
    {
        Source = image,
        Width = 25,
        Height = 25
    };
    Label la = new Label() 
    { 
        Content = text
    };
    sp.ColumnDefinitions.Add(gridCol1);
    sp.ColumnDefinitions.Add(gridCol2);
    Grid.SetColumn(im, 0);
    Grid.SetColumn(la, 1);
    sp.Children.Add(la);
    sp.Children.Add(im);
    lang_ComboBox.Items.Add(sp);
}

UPDATE 2 Hmmm I get it now, I use wrong word. 更新2嗯我现在得到它,我用错了字。 It should be "Hide" control design and still can choose from a list. 它应该是“隐藏”控件设计,仍然可以从列表中选择。 My bad sorry. 我很抱歉。 But i know how i can solve it with Anatoliy Nokolaev's Code. 但我知道如何用Anatoliy Nokolaev的代码来解决它。 To hide control design i use: 要隐藏控件设计我使用:

ToggleButton dropDownButton = GetFirstChildOfType<ToggleButton>(lang_ComboBox);
dropDownButton.Visibility = System.Windows.Visibility.Collapsed;

Unwanted behavior is now only that i cant show combobox dropdownmenu, but I'll invoke it programmatically by add on click event and should be good. 不需要的行为现在只是我不能显示组合框dropdownmenu,但我会通过添加点击事件以编程方式调用它,应该是好的。

If there is any easiest way to do this tell me :). 如果有任何最简单的方法,请告诉我:)。

To disable only the ToggleButton in ComboBox programmatically, you need to find this in the ComboBox control using VisualTreeHelper and assign a property IsEnabled to false , like this: 要以编程方式仅禁用ComboBoxToggleButton ,您需要使用VisualTreeHelperComboBox控件中找到它并将属性IsEnabled指定为false ,如下所示:

XAML

<Window x:Class="DisableComboBoxButton.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    Loaded="Window_Loaded">

    <StackPanel>
        <ComboBox Name="comboBox"
                  Width="100" 
                  Height="25"
                  SelectedIndex="0">

            <ComboBoxItem>Test1</ComboBoxItem>
            <ComboBoxItem>Test2</ComboBoxItem>
            <ComboBoxItem>Test3</ComboBoxItem>
        </ComboBox>

        <ComboBox Name="AllComboBoxDisabled"
                  Width="100" 
                  Height="25"
                  IsEnabled="False"
                  SelectedIndex="0">

            <ComboBoxItem>Test1</ComboBoxItem>
            <ComboBoxItem>Test2</ComboBoxItem>
            <ComboBoxItem>Test3</ComboBoxItem>
        </ComboBox>
    </StackPanel>
</Window>

Code-behind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        ToggleButton dropDownButton = GetFirstChildOfType<ToggleButton>(comboBox);

        dropDownButton.IsEnabled = false;
    }

    public static T GetFirstChildOfType<T>(DependencyObject dependencyObject) where T : DependencyObject
    {
        if (dependencyObject == null)
        {
            return null;
        }

        for (var i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++)
        {
            var child = VisualTreeHelper.GetChild(dependencyObject, i);

            var result = (child as T) ?? GetFirstChildOfType<T>(child);

            if (result != null)
            {
                return result;
            }
        }

        return null;
    }
}

Output

在此输入图像描述

Notes

Always use GetFirstChildOfType() function only when the control will be fully loaded, otherwise it will not find it and give null . 只有在控件完全加载时才使用GetFirstChildOfType()函数,否则它将找不到它并给出null In this case, I put this code in the event Window_Loaded which says that all the controls of the Window successfully load. 在这种情况下,我将此代码放在Window_Loaded事件中,该事件Window_Loaded Window的所有控件都成功加载。

Edit: another version

Not to say that this version is easier to implement, but it would be more correct and a bit easier to use. 并不是说这个版本更容易实现,但它更正确,更容易使用。

So, we need a template for your ComboBox , because it allows access to elements that are within the control. 因此,我们需要一个ComboBox模板,因为它允许访问控件中的元素。 Just like that, the ToggleButton can not be accessed from both the code and of XAML. 就像那样,无法从代码和XAML访问ToggleButton

We create attached dependency property that will serve the current ComboBox another property, such as which will give access to our button Visibility. 我们创建了附加的依赖属性,它将为当前的ComboBox另一个属性,例如,它可以访问我们的按钮Visibility。

Our property Visibility : 我们的财产Visibility

public static class ButtonExt
{
    public static readonly DependencyProperty VisibilityProperty;

    public static void SetVisibility(DependencyObject DepObject, Visibility value)
    {
        DepObject.SetValue(VisibilityProperty, value);
    }

    public static Visibility GetVisibility(DependencyObject DepObject)
    {
        return (Visibility)DepObject.GetValue(VisibilityProperty);
    }

    static ButtonExt()
    {
        PropertyMetadata VisibiltyPropertyMetadata = new PropertyMetadata(Visibility.Collapsed);

        VisibilityProperty = DependencyProperty.RegisterAttached("Visibility",
                                                            typeof(Visibility),
                                                            typeof(ButtonExt),
                                                            VisibiltyPropertyMetadata);
    }
}

Setter property in ComboBox template (skip version, full version see in project in App.xaml file): ComboBox模板中的Setter属性(跳过版本,完整版见App.xaml文件中的项目):

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type ComboBox}">
            <Grid>
                <ToggleButton Name="ToggleButton" 
                              Template="{StaticResource ComboBoxToggleButton}" 
                              IsChecked="{Binding Path=IsDropDownOpen, 
                                                  Mode=TwoWay, 
                                                  RelativeSource={RelativeSource TemplatedParent}}" 
                              Visibility="{TemplateBinding PropertiesExtension:ButtonExt.Visibility}" // <------ Here
                              Grid.Column="2" 
                              Focusable="False"                        
                              ClickMode="Press" />

Now, we are setting this property like this: 现在,我们将此属性设置为:

<ComboBox Name="comboBox"
          Style="{StaticResource ComboBoxBaseStyle}"
          PropertiesExtension:ButtonExt.Visibility="Visible"
          Width="100"
          Height="30"
          SelectedIndex="0">

    <ComboBoxItem>Test1</ComboBoxItem>
    <ComboBoxItem>Test2</ComboBoxItem>
    <ComboBoxItem>Test3</ComboBoxItem>
</ComboBox>

or in code-behind via Click event handlers: 或通过Click事件处理程序在代码隐藏中:

private void HideButton_Click(object sender, RoutedEventArgs e)
{ 
    ButtonExt.SetVisibility(comboBox, Visibility.Hidden);
}

private void ShowButton_Click(object sender, RoutedEventArgs e)
{
    ButtonExt.SetVisibility(comboBox, Visibility.Visible);
}    

Full version of example project is here . 完整版的示例项目就在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM