【问题标题】:Hide WPF ComboBox without visible items in XAML在 XAML 中隐藏没有可见项目的 WPF ComboBox
【发布时间】:2015-10-26 16:47:24
【问题描述】:

i当 ComboBox 的所有项目都折叠时,是否有一种纯 XAML 方法来隐藏 ComboBox?

例如,我有一个组合框:

<ComboBox ItemsSource="{Binding Persons}">
    <ComboBox.ItemContainerStyle>
        <Style TargetType="{x:Type ComboBoxItem}">
            <Setter Property="Visibility" Value="{Binding IsAlive, Converter={StaticResource BoolToVis}}" />
        </Style>
    </ComboBox.ItemContainerStyle>
</ComboBox>

预期行为:如果所有人都死了,组合框不可见,但如果至少一个人还活着,组合框是可见的(并且只显示活着的人)

我已经在代码中使用CollectionViewSourceFilter 和应用过滤器后CollectionViewSource.View 中的元素计数实现了此行为,但我更愿意在没有代码行为的情况下仅在 XAML 中实现该行为。

编辑: 我需要一个可在所有 ComboBoxes 中使用的通用解决方案,作为样式的一部分,而不是分配 Person 类型或 IsAlive 属性......所以解决方案应该只取决于包含项目的可见性属性

【问题讨论】:

  • 为什么不做你已经为单个项目做的同样的事情呢? IE。将ComboBox.Visibility 属性绑定到Persons 属性,并使用转换器扫描集合,如果任何项目将IsAlive 设置为true,则返回Visibility.Visible,否则返回Visibility.Collapsed。由于您显然已经知道这种方法,因此如果您能在问题中解释为什么这对这个特定目标不起作用,那将会很有帮助。更好的是,提供 a good, minimal, complete code example 来显示所有这些。
  • @PeterDuniho 因为我需要一个可在所有 CheckBox 中使用的通用解决方案作为样式的一部分,而不是分配 Person 类型或 IsAlive 属性......所以解决方案应该只取决于包含项目的可见性属性
  • 复选框还是组合框?
  • 我不认为你可以做“纯 XAML”。在某些时候,一些代码隐藏需要将集合的状态转换为可见性。也就是说,您可以绑定到ItemsSource 集合,然后在您的转换器中使用ItemContainerGenerator.ContainerFromItem() 来检索代表您的数据项的可视化容器。从中,您可以检查其可见性,而不必编写特定于模型的代码。
  • 您的视图模型是否有理由必须返回所有生者和死者?相反,如果您绑定到“LivingPersons”,那么通过将 ComboBox 类的 HasItems 属性转换为 Visibility 属性,可以简化您的可见性问题。另外,您为什么使用看起来是您的手卷 BoolToVis 转换器而不是 System.Windows.Controls 中可用的 BooleanToVisibilityConverter 类?

标签: c# wpf xaml


【解决方案1】:

如果 items 属性为 null、空或其中的所有项目不可见 (Visibility.Collapsed),您可以使用此附加属性隐藏组合框

创建一个新的类 ComboBoxExt(或任何你想叫它的名字)然后添加一个附加属性。 (提示:您可以在 Visual Studio 中输入“propa”,然后按两次 Tab,它会为您提供附加属性的模板)

public class ComboBoxExt
  {
    public static bool GetHideOnEmpty(DependencyObject obj)
    {
      return (bool)obj.GetValue(HideOnEmptyProperty);
    }

    public static void SetHideOnEmpty(DependencyObject obj, bool value)
    {
      obj.SetValue(HideOnEmptyProperty, value);
    }

    public static readonly DependencyProperty HideOnEmptyProperty =
        DependencyProperty.RegisterAttached("HideOnEmpty", typeof(bool), typeof(ComboBoxExt), new UIPropertyMetadata(false, HideOnEmptyChanged));

    private static void HideOnEmptyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      var cbox = d as ComboBox;

      if (cbox == null)
        return;

      HideComboBox(cbox, (bool)e.NewValue);
    }
    //This is where we check if all the items are not visible
    static void HideComboBox(ComboBox cbox, bool val)
    {
      //First, we have to know if the HideOnEmpty property is set to true. 
      if (val)
      {
        //Check if the combobox is either null or empty
        if (cbox.Items == null || cbox.Items.Count < 1)
          cbox.Visibility = Visibility.Collapsed; //Hide the combobox
        else
        {
          bool hide = true;
          //Check if all the items are not visible.  
          foreach (ComboBoxItem i in cbox.Items)
          {
            if (i.Visibility == Visibility.Visible)
            {
              hide = false;
              break;
            }
          }

          //If one or more items above is visible we won't hide the combobox.
          if (!hide)
            cbox.Visibility = Visibility.Visible;
          else
            cbox.Visibility = Visibility.Collapsed;
        }
      }
    }
  }

现在您可以在所需的每个组合框中重复使用附加属性。您只需将 HideOnEmpty 设置为 true。

<ComboBox local:ComboBoxExt.HideOnEmpty="True"/>

使用此解决方案,您将无需编写代码,并且可以在所需的每个组合框上重复使用附加属性 HideOnEmpty。

【讨论】:

    【解决方案2】:

    您“过滤”组合框项目的方法不正确且性能极差[1]。您应该使用CollectionView/CollectionViewSource 过滤Persons 集合,而不是在ItemContainerStyle 中分配可见性。实现这一点后,您可以使用绑定的CollectionView.IsEmpty 属性在ComboBox.Visibility 属性中使用简单的绑定和转换器。

    [1] 关于性能:目前,在评估 Visibility 绑定之前,将为每个 Person 对象创建一个容器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-15
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 2020-10-30
      • 2016-08-27
      • 1970-01-01
      • 2021-02-25
      相关资源
      最近更新 更多