WPF ComboBox 禁用时不显示任何选定内容 (IsEnabled == false)

发布于 2024-10-13 01:14:42 字数 1533 浏览 10 评论 0原文

我正在考虑不同的方法,让 WPF ComboBox 显示空白,就好像当 IsEnabled 设置为 false 时没有选择任何内容。像往常一样,我试图在不必重新定义 ComboBox 的整个控件模板的情况下执行此操作,这始终是我在 WPF 中遇到的一个难题。如果有人有比重新定义整个 ComboBox 控件模板更优雅的解决方案,请告诉我。

我想要做的原因是我有一个代表“全部”选项的 CheckBox ,选中时它会禁用用于仅选择一个的 ComboBox单个项目。如果我的 CheckBox 被选中,有时用户会在看到 ComboBox 中剩余的值时感到困惑,因为该值在 UI 的该状态下没有任何意义。

另一个要求是解决方案不能修改 ComboBoxSelectedValueSelectedIndexSelectedItem 值,因为我会喜欢在用户取消选中“全部”CheckBox 的情况下保留先前选择的项目。

基于 HCL 答案的解决方案:

<ComboBox IsEnabled="{Binding ElementName=myCheckBox, Path=IsChecked}"
          ItemsSource="{Binding Path=MyItems}"
          SelectedValue="{Binding Path=MySelectedItem}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <ContentControl x:Name="content" Content="{Binding MyItemDescription}" />
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ComboBox}, Path=IsEnabled}"
                             Value="False">
                    <Setter TargetName="content"
                            Property="Visibility"
                            Value="Hidden" />
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

I'm thinking out different ways to have a WPF ComboBox show blank as if nothing is selected when IsEnabled is set to false. Like always I'm trying to do this without having to redefine the whole control template for the ComboBox which is always a struggle I have with WPF. If anybody has any solutions more elegant than redefining the whole ComboBox control template please let me know.

The reason for what I'm trying to do is I have a CheckBox that represents an "All" option and when checked it disables the ComboBox which is used to pick only a single individual item. If my CheckBox is checked it is sometimes confusing to the users to see a value remaining in the ComboBox since that value has no meaning in that state of the UI.

Another requirement is that the solution cannot modify the SelectedValue, SelectedIndex, or SelectedItem values of the ComboBox since I would like to retain the previuosly selected item in the case that the users unchecks the "All" CheckBox.

Solution based on HCL's answer:

<ComboBox IsEnabled="{Binding ElementName=myCheckBox, Path=IsChecked}"
          ItemsSource="{Binding Path=MyItems}"
          SelectedValue="{Binding Path=MySelectedItem}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <ContentControl x:Name="content" Content="{Binding MyItemDescription}" />
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ComboBox}, Path=IsEnabled}"
                             Value="False">
                    <Setter TargetName="content"
                            Property="Visibility"
                            Value="Hidden" />
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

著墨染雨君画夕 2024-10-20 01:14:42

您可以使用触发器执行某些操作:

尝试在禁用该框时将 ItemTemplate 设置为空的 DataTemplate。这将影响所选项目的渲染并因此将其隐藏。

另一个简单但不是很好的解决方案是将前景色设置为与背景色相同。

You can do something with triggers:

Try setting the ItemTemplate to an empty DataTemplate when the box is disabled. This will affect the rendering of the selected item and therefore hide it.

Another simple but not very nice solution would be to set the foreground color to the same as a background color.

最初的梦 2024-10-20 01:14:42

我相信您可以使用样式来完成此操作,而不是重新定义控件模板。使用 IsEnabled 属性上的触发器来设置组合框中显示的文本。更改 SelectedItem 将是我的第一个方法,但由于您不想这样做,因此您可能会发现成功设置 DisplayMemberPath。像这样的东西(未经测试)...

<Style TargetType="{x:Type ComboBox}">
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="False">
            <Trigger.Setters>
                <Setter Property="DisplayMemberPath" Value="{x:Null}"/>
            </Trigger.Setters>
        </Trigger>
    </Style.Triggers>
</Style>

I believe you can do this with a Style, rather than redefining the control template. Use a Trigger on the IsEnabled property to set the text shown in the ComboBox. Altering the SelectedItem would be my first approach, but since you don't want to do that, you may find success setting the DisplayMemberPath. Something like this (untested)...

<Style TargetType="{x:Type ComboBox}">
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="False">
            <Trigger.Setters>
                <Setter Property="DisplayMemberPath" Value="{x:Null}"/>
            </Trigger.Setters>
        </Trigger>
    </Style.Triggers>
</Style>
半边脸i 2024-10-20 01:14:42

这是一种可以满足您需求的样式。它采用了我一直使用的一种技术:包含控件的多个版本的网格,以及确保在任何时间只有一个版本可见的数据触发器。

    <ComboBox.Style>
      <Style TargetType="ComboBox">
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="ComboBox">
              <DockPanel>
                <CheckBox x:Name="IsActive" DockPanel.Dock="Left"/>
                <Grid>
                  <ComboBox
                    ItemsSource="{TemplateBinding ItemsSource}"
                    SelectedItem="{TemplateBinding SelectedItem}"
                    SelectedIndex="{TemplateBinding SelectedIndex}"
                    SelectedValue="{TemplateBinding SelectedValue}">
                    <ComboBox.Style>
                      <Style TargetType="ComboBox">
                        <Setter Property="Visibility" Value="Visible"/>
                        <Style.Triggers>
                          <DataTrigger Binding="{Binding ElementName=IsActive, Path=IsChecked}" Value="False">
                            <Setter Property="Visibility" Value="Collapsed"/>
                          </DataTrigger>
                        </Style.Triggers>
                      </Style>
                    </ComboBox.Style>
                  </ComboBox>
                  <ComboBox>
                    <ComboBox.Style>
                      <Style TargetType="ComboBox">
                        <Setter Property="Visibility" Value="Collapsed"/>
                        <Style.Triggers>
                          <DataTrigger Binding="{Binding ElementName=IsActive, Path=IsChecked}" Value="False">
                            <Setter Property="Visibility" Value="Visible"/>
                          </DataTrigger>
                        </Style.Triggers>
                      </Style>
                    </ComboBox.Style>                      
                  </ComboBox>
                </Grid>
              </DockPanel>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </ComboBox.Style>

这将按照您的需要保留所选项目、所选索引和所选值。事实上,它在这方面做得有点太好了。实际上没有办法告诉用户已停用组合框,因为 ComboBox 上没有公开此信息的属性。我实际上可能会将其实现为从 ComboBox 派生的自定义控件,该控件将复选框的值公开为 IsActive 属性。还有很多其他方法可以做到这一点。

Here's a style that does what you want. It employs a technique that I use all the time: a grid that contains multiple versions of the control, and data triggers that ensure that only one version is visible at any one time.

    <ComboBox.Style>
      <Style TargetType="ComboBox">
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="ComboBox">
              <DockPanel>
                <CheckBox x:Name="IsActive" DockPanel.Dock="Left"/>
                <Grid>
                  <ComboBox
                    ItemsSource="{TemplateBinding ItemsSource}"
                    SelectedItem="{TemplateBinding SelectedItem}"
                    SelectedIndex="{TemplateBinding SelectedIndex}"
                    SelectedValue="{TemplateBinding SelectedValue}">
                    <ComboBox.Style>
                      <Style TargetType="ComboBox">
                        <Setter Property="Visibility" Value="Visible"/>
                        <Style.Triggers>
                          <DataTrigger Binding="{Binding ElementName=IsActive, Path=IsChecked}" Value="False">
                            <Setter Property="Visibility" Value="Collapsed"/>
                          </DataTrigger>
                        </Style.Triggers>
                      </Style>
                    </ComboBox.Style>
                  </ComboBox>
                  <ComboBox>
                    <ComboBox.Style>
                      <Style TargetType="ComboBox">
                        <Setter Property="Visibility" Value="Collapsed"/>
                        <Style.Triggers>
                          <DataTrigger Binding="{Binding ElementName=IsActive, Path=IsChecked}" Value="False">
                            <Setter Property="Visibility" Value="Visible"/>
                          </DataTrigger>
                        </Style.Triggers>
                      </Style>
                    </ComboBox.Style>                      
                  </ComboBox>
                </Grid>
              </DockPanel>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </ComboBox.Style>

This preserves the selected item, selected index, and selected value, just as you want. In fact, it does this a little too well; there's not actually a way of telling that the user deactivated the combo box, since there's no property on ComboBox that exposes this information. I'd probably actually implement this as a custom control derived from ComboBox that exposed the value of the check box as an IsActive property. There are lots of other ways to do it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文