通过属性绑定禁用组合框的切换按钮或弹出下拉菜单

问题描述 投票:0回答:2

我希望能够通过在 ViewModel 中设置属性来禁用用户的组合框。 最后,在某些情况下,用户应该只能查看 SelectedItem。

Stackoverflow 上有一些类似的问题,但没有一个能让我找到这个问题的解决方案。到目前为止,我通过窗口中的工具箱放置了一个组合框,并通过选择选项编辑模板的副本

开始编辑整个组合框模板的副本
1.尝试直接编辑切换按钮样式 - 隐藏整个组合框
<Setter Property="Template">
  <Setter.Value>
    <ControlTemplate TargetType="{x:Type ToggleButton}">
      <ControlTemplate.Triggers>
        <DataTrigger Binding="{Binding IsCombboxEnabled}" Value="True">
          <Setter Property="Visibility" Value="Visible" />
        </DataTrigger>
        <DataTrigger Binding="{Binding IsCombboxEnabled}" Value="False">
          <Setter Property="Visibility" Value="Hidden" />
        </DataTrigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
   </Setter.Value>
 </Setter>
  • 这隐藏了整个组合框
  • 设置
    IsEnabled
    ,禁用整个组合框,但我希望能够使用f.e.禁用下拉列表时文本块的编辑属性
  • IsChecked
    样式中的属性触发器不会改变任何内容

2.直接在 ToggleButton 中设置 IsChecked 有效

这更接近解决方案:直接在 ToggleButton 中编辑 IsChecked 用法:

            <ToggleButton x:Name="toggleButton" 
                          Background="{TemplateBinding Background}" 
                          BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 
                          Grid.ColumnSpan="2" 
                          IsChecked="{Binding IsCombboxEnabled}" 
                          Style="{StaticResource ComboBoxToggleButton}"/>

我想这已经让我成功了一半。现在根本无法打开 PopUp。 我现在正在努力在属性和数据上设置一种 MultiDataTrigger 绑定,以组合

IsChecked="{Binding IsCombboxEnabled}"
和替换的行
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource Mode=TemplatedParent}}"

如何正确组合这两个语句?或者有没有更干净、优雅的方式来实现这一点?

Xaml 代码(自定义 ComboboxEditTemplate 被省略)
<Window x:Class="WpfApp1.MainWindow"
    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:local="clr-namespace:WpfApp1"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800"
xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2">
<Window.Resources>
    <Style x:Key="FocusVisual">
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate>
                    <Rectangle Margin="2" StrokeDashArray="1 2" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" SnapsToDevicePixels="true" StrokeThickness="1"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <LinearGradientBrush x:Key="ComboBox.Static.Background" EndPoint="0,1" StartPoint="0,0">
        <GradientStop Color="#FFF0F0F0" Offset="0.0"/>
        <GradientStop Color="#FFE5E5E5" Offset="1.0"/>
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ComboBox.Static.Border" Color="#FFACACAC"/>
    <SolidColorBrush x:Key="ComboBox.Static.Glyph" Color="#FF606060"/>
    <SolidColorBrush x:Key="ComboBox.Static.Editable.Background" Color="#FFFFFFFF"/>
    <SolidColorBrush x:Key="ComboBox.Static.Editable.Border" Color="#FFABADB3"/>
    <SolidColorBrush x:Key="ComboBox.Static.Editable.Button.Background" Color="Transparent"/>
    <SolidColorBrush x:Key="ComboBox.Static.Editable.Button.Border" Color="Transparent"/>
    <LinearGradientBrush x:Key="ComboBox.MouseOver.Background" EndPoint="0,1" StartPoint="0,0">
        <GradientStop Color="#FFECF4FC" Offset="0.0"/>
        <GradientStop Color="#FFDCECFC" Offset="1.0"/>
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ComboBox.MouseOver.Border" Color="#FF7EB4EA"/>
    <SolidColorBrush x:Key="ComboBox.MouseOver.Glyph" Color="#FF000000"/>
    <SolidColorBrush x:Key="ComboBox.MouseOver.Editable.Background" Color="#FFFFFFFF"/>
    <SolidColorBrush x:Key="ComboBox.MouseOver.Editable.Border" Color="#FF7EB4EA"/>
    <LinearGradientBrush x:Key="ComboBox.MouseOver.Editable.Button.Background" EndPoint="0,1" StartPoint="0,0">
        <GradientStop Color="#FFEBF4FC" Offset="0.0"/>
        <GradientStop Color="#FFDCECFC" Offset="1.0"/>
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ComboBox.MouseOver.Editable.Button.Border" Color="#FF7EB4EA"/>
    <LinearGradientBrush x:Key="ComboBox.Pressed.Background" EndPoint="0,1" StartPoint="0,0">
        <GradientStop Color="#FFDAECFC" Offset="0.0"/>
        <GradientStop Color="#FFC4E0FC" Offset="1.0"/>
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ComboBox.Pressed.Border" Color="#FF569DE5"/>
    <SolidColorBrush x:Key="ComboBox.Pressed.Glyph" Color="#FF000000"/>
    <SolidColorBrush x:Key="ComboBox.Pressed.Editable.Background" Color="#FFFFFFFF"/>
    <SolidColorBrush x:Key="ComboBox.Pressed.Editable.Border" Color="#FF569DE5"/>
    <LinearGradientBrush x:Key="ComboBox.Pressed.Editable.Button.Background" EndPoint="0,1" StartPoint="0,0">
        <GradientStop Color="#FFDAEBFC" Offset="0.0"/>
        <GradientStop Color="#FFC4E0FC" Offset="1.0"/>
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ComboBox.Pressed.Editable.Button.Border" Color="#FF569DE5"/>
    <SolidColorBrush x:Key="ComboBox.Disabled.Background" Color="#FFF0F0F0"/>
    <SolidColorBrush x:Key="ComboBox.Disabled.Border" Color="#FFD9D9D9"/>
    <SolidColorBrush x:Key="ComboBox.Disabled.Glyph" Color="#FFBFBFBF"/>
    <SolidColorBrush x:Key="ComboBox.Disabled.Editable.Background" Color="#FFFFFFFF"/>
    <SolidColorBrush x:Key="ComboBox.Disabled.Editable.Border" Color="#FFBFBFBF"/>
    <SolidColorBrush x:Key="ComboBox.Disabled.Editable.Button.Background" Color="Transparent"/>
    <SolidColorBrush x:Key="ComboBox.Disabled.Editable.Button.Border" Color="Transparent"/>
    <Style x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="IsTabStop" Value="false"/>
        <Setter Property="Focusable" Value="false"/>
        <Setter Property="ClickMode" Value="Press"/>
        <Setter Property="IsChecked" Value="{Binding IsToggleButtonEnabled}"></Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ToggleButton}">
                    <Border x:Name="templateRoot" 
                            Background="{StaticResource ComboBox.Static.Background}" 
                            BorderBrush="{StaticResource ComboBox.Static.Border}" 
                            BorderThickness="{TemplateBinding BorderThickness}"
                            SnapsToDevicePixels="true">
                        <Border x:Name="splitBorder" BorderBrush="Transparent" 
                                BorderThickness="1"
                                HorizontalAlignment="Right" 
                                Margin="0" 
                                SnapsToDevicePixels="true" 
                                Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}">
                            <Path x:Name="arrow" Data="F1 M 0,0 L 2.667,2.66665 L 5.3334,0 L 5.3334,-1.78168 L 2.6667,0.88501 L0,-1.78168 L0,0 Z" Fill="{StaticResource ComboBox.Static.Glyph}" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center"/>
                        </Border>
                    </Border>
                    <ControlTemplate.Triggers>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true"/>
                                <Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Mode=Self}}" Value="false"/>
                                <Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource Mode=Self}}" Value="false"/>
                                <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Mode=Self}}" Value="true"/>
                            </MultiDataTrigger.Conditions>
                            <Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Static.Editable.Background}"/>
                            <Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Static.Editable.Border}"/>
                            <Setter Property="Background" TargetName="splitBorder" Value="{StaticResource ComboBox.Static.Editable.Button.Background}"/>
                            <Setter Property="BorderBrush" TargetName="splitBorder" Value="{StaticResource ComboBox.Static.Editable.Button.Border}"/>
                        </MultiDataTrigger>
                        <Trigger Property="IsMouseOver" Value="true">
                            <Setter Property="Fill" TargetName="arrow" Value="{StaticResource ComboBox.MouseOver.Glyph}"/>
                        </Trigger>
                        <!--<DataTrigger Binding="{Binding IsToggleButtonEnabled}" Value="True">
                            <Setter Property="IsEnabled" Value="True" />
                        </DataTrigger>
                        <DataTrigger Binding="{Binding IsToggleButtonEnabled}" Value="False">
                            <Setter Property="IsEnabled" Value="False" />
                        </DataTrigger>-->
                        <DataTrigger Binding="{Binding IsToggleButtonEnabled}" Value="True">
                            <Setter Property="IsChecked" Value="True" />
                        </DataTrigger>
                        <DataTrigger Binding="{Binding IsToggleButtonEnabled}" Value="False">
                            <Setter Property="IsChecked" Value="False" />
                        </DataTrigger>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Mode=Self}}" Value="true"/>
                                <Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="false"/>
                            </MultiDataTrigger.Conditions>
                            <Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.MouseOver.Background}"/>
                            <Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.MouseOver.Border}"/>
                        </MultiDataTrigger>
                        
                        <!--<MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsChecked" Value="True" />
                                <Condition Property="{Binding RelativeSource={RelativeSource Mode=Self},Path=IsToggleButtonEnabled}" Value="True" />
                            </MultiTrigger.Conditions>
                            <MultiTrigger.Setters>
                                <Setter Property="IsChecked" Value="True" />
                            </MultiTrigger.Setters>
                        </MultiTrigger>-->


                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Mode=Self}}" Value="true"/>
                                <Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true"/>
                            </MultiDataTrigger.Conditions>
                            <Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.MouseOver.Editable.Background}"/>
                            <Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.MouseOver.Editable.Border}"/>
                            <Setter Property="Background" TargetName="splitBorder" Value="{StaticResource ComboBox.MouseOver.Editable.Button.Background}"/>
                            <Setter Property="BorderBrush" TargetName="splitBorder" Value="{StaticResource ComboBox.MouseOver.Editable.Button.Border}"/>
                        </MultiDataTrigger>
                        <Trigger Property="IsPressed" Value="true">
                            <Setter Property="Fill" TargetName="arrow" Value="{StaticResource ComboBox.Pressed.Glyph}"/>
                        </Trigger>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource Mode=Self}}" Value="true"/>
                                <Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="false"/>
                            </MultiDataTrigger.Conditions>
                            <Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Pressed.Background}"/>
                            <Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Pressed.Border}"/>
                        </MultiDataTrigger>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource Mode=Self}}" Value="true"/>
                                <Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true"/>
                            </MultiDataTrigger.Conditions>
                            <Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Pressed.Editable.Background}"/>
                            <Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Pressed.Editable.Border}"/>
                            <Setter Property="Background" TargetName="splitBorder" Value="{StaticResource ComboBox.Pressed.Editable.Button.Background}"/>
                            <Setter Property="BorderBrush" TargetName="splitBorder" Value="{StaticResource ComboBox.Pressed.Editable.Button.Border}"/>
                        </MultiDataTrigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Fill" TargetName="arrow" Value="{StaticResource ComboBox.Disabled.Glyph}"/>
                        </Trigger>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Mode=Self}}" Value="false"/>
                                <Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="false"/>
                            </MultiDataTrigger.Conditions>
                            <Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Disabled.Background}"/>
                            <Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Disabled.Border}"/>
                        </MultiDataTrigger>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Mode=Self}}" Value="false"/>
                                <Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true"/>
                            </MultiDataTrigger.Conditions>
                            <Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Disabled.Editable.Background}"/>
                            <Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Disabled.Editable.Border}"/>
                            <Setter Property="Background" TargetName="splitBorder" Value="{StaticResource ComboBox.Disabled.Editable.Button.Background}"/>
                            <Setter Property="BorderBrush" TargetName="splitBorder" Value="{StaticResource ComboBox.Disabled.Editable.Button.Border}"/>
                        </MultiDataTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <ControlTemplate x:Key="ComboBoxTemplate" TargetType="{x:Type ComboBox}">
        <Grid x:Name="templateRoot" SnapsToDevicePixels="true">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
            </Grid.ColumnDefinitions>
            <Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource Mode=TemplatedParent}}" Margin="1" Placement="Bottom" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}">
                <theme:SystemDropShadowChrome x:Name="shadow" Color="Transparent" MinWidth="{Binding ActualWidth, ElementName=templateRoot}" MaxHeight="{TemplateBinding MaxDropDownHeight}">
                    <Border x:Name="dropDownBorder" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1">
                        <ScrollViewer x:Name="DropDownScrollViewer">
                            <Grid x:Name="grid" RenderOptions.ClearTypeHint="Enabled">
                                <Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
                                    <Rectangle x:Name="opaqueRect" Fill="{Binding Background, ElementName=dropDownBorder}" Height="{Binding ActualHeight, ElementName=dropDownBorder}" Width="{Binding ActualWidth, ElementName=dropDownBorder}"/>
                                </Canvas>
                                <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </Grid>
                        </ScrollViewer>
                    </Border>
                </theme:SystemDropShadowChrome>
            </Popup>
            <ToggleButton x:Name="toggleButton" 
                          Background="{TemplateBinding Background}" 
                          BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 
                          Grid.ColumnSpan="2" 
                          IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource Mode=TemplatedParent}}" 
                          Style="{StaticResource ComboBoxToggleButton}"/>
            <ContentPresenter x:Name="contentPresenter" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" 
                              ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" 
                              Content="{TemplateBinding SelectionBoxItem}" 
                              ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" 
                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                              IsHitTestVisible="false" Margin="{TemplateBinding Padding}" 
                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>
        <ControlTemplate.Triggers>
            
               
            
            <Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
                <Setter Property="Margin" TargetName="shadow" Value="0,0,5,5"/>
                <Setter Property="Color" TargetName="shadow" Value="#71000000"/>
            </Trigger>
            <Trigger Property="HasItems" Value="false">
                <Setter Property="Height" TargetName="dropDownBorder" Value="95"/>
            </Trigger>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsGrouping" Value="true"/>
                    <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
                </MultiTrigger.Conditions>
                <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
            </MultiTrigger>
            <Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="false">
                <Setter Property="Canvas.Top" TargetName="opaqueRect" 
                        Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/>
                <Setter Property="Canvas.Left" TargetName="opaqueRect" 
                        Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    <Style x:Key="CmbboxToggleButtonTemplate" TargetType="{x:Type ComboBox}">
        <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
        <Setter Property="Background" Value="{StaticResource ComboBox.Static.Background}"/>
        <Setter Property="BorderBrush" Value="{StaticResource ComboBox.Static.Border}"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
        <Setter Property="Padding" Value="6,3,5,3"/>
        <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
        <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
        <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
        <Setter Property="Template" Value="{StaticResource ComboBoxTemplate}"/>

    </Style>
</Window.Resources>
<Window.DataContext>
    <local:ViewModel></local:ViewModel>
</Window.DataContext>

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>
    <ComboBox Style="{DynamicResource CmbboxToggleButtonTemplate}" 
              ItemsSource="{Binding Items}"
              SelectedItem="{Binding SelectedItem}"
              Grid.Column="1"  Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200">
    </ComboBox>
    <Button Content="On/Off" Margin="50" Command="{Binding SwitchCommand}"></Button>
    <TextBlock Grid.Row="1 " Grid.Column="0" Text="{Binding State}"></TextBlock>
</Grid>
</Window>
ViewModel(INotifyPropertyChanged 实现被遗漏)
public class ViewModel : INotifyPropertyChanged
{
private string state;
private List<string> items;
private string selectedItem;
private bool isToggleButtonEnabled;
private Visibility visibilityCombobox;
public ViewModel()
{
    Items = new List<string> { "item1", "item2", "item3" };
    State = "On";
}

public List<string> Items
{
    get => items;
    set
    {
        items = value;
        OnPropertyChanged();
    }
}

public ICommand SwitchCommand => new RelayCommand(() =>
{
    VisibilityCombobox = visibilityCombobox == Visibility.Collapsed ?  Visibility.Visible : Visibility.Collapsed;
});

public bool IsToggleButtonEnabled
{
    get => isToggleButtonEnabled;
    set
    {
        isToggleButtonEnabled = value;
        OnPropertyChanged();
    }
}

public Visibility VisibilityCombobox
{
    get => visibilityCombobox;
    set
    {
        visibilityCombobox = value;
        State = value == Visibility.Visible ? "On" : "Off";
        OnPropertyChanged();
    }
}

public string SelectedItem
{
    get => selectedItem;
    set
    {
        selectedItem = value;
        OnPropertyChanged();
    }
}

public string State
{
    get => state;
    set
    {
        state = value;
        OnPropertyChanged();
    }}}
c# wpf xaml combobox controltemplate
2个回答
0
投票

我认为您可以大大简化您的方法,并且仍然可以实现我认为您正在寻找的目标。

我希望能够通过在 ViewModel 中设置属性来禁用用户的组合框。最后,在某些情况下,用户应该只能查看 SelectedItem。

您的问题并不完全清楚,但我认为您想在禁用

ComboBox
时隐藏文本。这也可以理解为您希望它在禁用时看起来像
TextBlock
,所以我将提供这两个答案。

禁用时隐藏文本

您可以使用

ViewModel
类来控制
ComboBox.Text
属性的状态依赖性,该属性控制显示的内容。通过这样做,您无需担心完全覆盖
ComboBox
模板。

public bool IsToggleButtonEnabled
{
    get => isToggleButtonEnabled;
    set
    {
        isToggleButtonEnabled = value;
        OnPropertyChanged();
        // also notify that the dependent properties changed
        OnPropertyChanged(nameof(DisplayText));
        OnPropertyChanged(nameof(State));
    }
}

public string DisplayText 
{ 
    get => IsToggleButtonEnabled ? selectedItem : string.Empty; 
}
        <ToggleButton IsChecked="{Binding IsToggleButtonEnabled}"
                      Content="{Binding State}" />
        <ComboBox Grid.Column="1"
                  ItemsSource="{Binding Items}"
                  SelectedItem="{Binding SelectedItem}"
                  IsEnabled="{Binding IsToggleButtonEnabled}"
                  Text="{Binding DisplayText, Mode=OneWay}"/>

结果:

禁用时显示为
TextBlock

如果您的目标是使 ComboBox 在禁用时看起来像 TextBlock,则可以简单地根据状态交换控件。

public bool IsToggleButtonEnabled
{
    get => isToggleButtonEnabled;
    set
    {
        isToggleButtonEnabled = value;
        OnPropertyChanged();
        // also notify that the dependent properties changed
        OnPropertyChanged(nameof(ComboBoxVisibility));
        OnPropertyChanged(nameof(TextBlockVisibility));
    }
}
public Visibility ComboBoxVisibility => IsToggleButtonEnabled ? Visibility.Visible : Visibility.Collapsed;
public Visibility TextBlockVisibility => IsToggleButtonEnabled ? Visibility.Hidden : Visibility.Visible;
        <ToggleButton IsChecked="{Binding IsToggleButtonEnabled}"
                      Content="{Binding State}"
                      Grid.Row="1"/>
        <ComboBox Grid.Column="1" 
                  Grid.Row="1"
                  ItemsSource="{Binding Items}"
                  SelectedItem="{Binding SelectedItem}"
                  IsEnabled="{Binding IsToggleButtonEnabled}"
                  Text="{Binding DisplayText, Mode=OneWay}"
                  Visibility="{Binding ComboBoxVisibility}"/>
        <TextBlock Grid.Column="1"
                   Grid.Row="1"
                   Padding="6,3"
                   Text="{Binding SelectedItem}"
                   Visibility="{Binding TextBlockVisibility}"/>

您可以在此处查看生成这两个 gif 的完整代码:


0
投票

您可以处理

ComboBox.DropDownOpened
事件并强制关闭下拉菜单:

MainWindow.xaml

<ComboBox DropDownOpened="ComboBox_DropDownOpened" />

MainWindow.xaml.cs

private void ComboBox_DropDownOpened(object sender, EventArgs e)
{
  var comboBox = (ComboBox)sender;

  bool canDropDownOpen = // TODO::Calculate value e.g. based on other values 
  if (!canDropDownOpen)
  {
    comboBox.IsDropDownOpen = false;
  }
}

或延长

ComboBox
(推荐):

MainWindow.xaml

<ExtendedComboBox CanDropDownOpen="{Binding SomeProperty}" />

扩展组合框.cs

public class ExtendedComboBox : ComboBox
{
  public bool CanDropDownOpen
  {
    get => (bool)GetValue(CanDropDownOpenProperty);
    set => SetValue(CanDropDownOpenProperty, value);
  }

  public static readonly DependencyProperty CanDropDownOpenProperty = DependencyProperty.Register(
    "CanDropDownOpen", 
    typeof(bool), 
    typeof(ExtendedComboBox), 
    new PropertyMetadata(true));

  static ExtendedComboBox() 
    => IsDropDownOpenProperty.OverrideMetadata(typeof(ExtendedComboBox), new FrameworkPropertyMetadata(default(bool), null, OnCoerceIsDropDownOpenValue));

  // Reject any value and overwrite it with 'false' if CanDropDownOpen is 'false'
  private static object OnCoerceIsDropDownOpenValue(DependencyObject d, object baseValue)
  {
    var extendedComboBox = (ExtendedComboBox)d;
    return extendedComboBox.CanDropDownOpen 
      ? baseValue 
      : false;
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.