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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20933186/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:24:32  来源:igfitidea点击:

WPF ComboBox Hide (Disable) DropDown Button Programmatically

c#wpfcombobox

提问by Artur Szymański

I would like to know how to disable ComboBox DropDown Button Programmatically. I had seen many similar subjects but all of these have a XAML solution.

我想知道如何以编程方式禁用 ComboBox DropDown 按钮。我看过很多类似的主题,但所有这些都有一个 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

更新

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 2Hmmm I get it now, I use wrong word. 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. To hide control design i use:

更新 2嗯,我现在明白了,我用错了词。它应该是“隐藏”控件设计并且仍然可以从列表中进行选择。我的对不起。但我知道如何使用 Anatoliy Nokolaev 的代码来解决它。要隐藏控件设计,我使用:

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.

不需要的行为现在只是我无法显示组合框下拉菜单,但我将通过添加点击事件以编程方式调用它并且应该很好。

If there is any easiest way to do this tell me :).

如果有任何最简单的方法可以做到这一点,请告诉我:)。

采纳答案by Anatoliy Nikolaev

To disable only the ToggleButtonin ComboBoxprogrammatically, you need to find this in the ComboBoxcontrol using VisualTreeHelperand assign a property IsEnabledto false, like this:

ToggleButtonComboBox编程方式仅禁用in ,您需要在ComboBox控件中找到它usingVisualTreeHelper并将属性分配IsEnabledfalse,如下所示:

XAML

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

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

Output

enter image description here

在此处输入图片说明

Notes

Notes

Always use GetFirstChildOfType()function only when the control will be fully loaded, otherwise it will not find it and give null. In this case, I put this code in the event Window_Loadedwhich says that all the controls of the Window successfully load.

始终GetFirstChildOfType()仅在控件完全加载时使用function ,否则它将找不到它并给出null。在这种情况下,我将此代码放在Window_Loaded表示 Window 的所有控件成功加载的事件中。

Edit: another version

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. Just like that, the ToggleButtoncan not be accessed from both the code and of XAML.

因此,我们需要一个用于您的模板ComboBox,因为它允许访问控件内的元素。就像那样,ToggleButton不能从代码和 XAML 中访问。

We create attached dependency property that will serve the current ComboBoxanother 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.xamlfile):

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.

示例项目的完整版本在这里