【问题标题】:WPF How to set visibility of parent container from a data templateWPF 如何从数据模板设置父容器的可见性
【发布时间】:2014-03-07 18:45:13
【问题描述】:

我已经为我的 Component 对象创建了一个 DataTemplate。我添加了 DataTrigger 以确定组件是否应该可见。本质上,我们有过滤器,代码检查这些过滤器以确定组件应该是可见的还是折叠的。我遇到的问题是我希望触发器将可见性设置为父容器的“折叠”或“可见”,即 ListBoxItem。该代码有效,但将其设置在 Border 处。

模板的开头是这样的:

   <DataTemplate DataType="{x:Type local:Component}">
                <Border .....

我正在为我的触发器提供代码,我将在下面解释我尝试了哪些但没有成功。

        <DataTemplate.Triggers>
            <DataTrigger Value="True">
                <DataTrigger.Binding>
                    <MultiBinding Converter="{StaticResource TrueWhenComponentIsVisible}">
                        <Binding Path="Type" />
                        <Binding Path="Dependency"/>
                        <Binding Path="SelectedType" RelativeSource="{RelativeSource FindAncestor, AncestorType=Window}"/>
                        <Binding Path="SelectedDepencency" RelativeSource="{RelativeSource FindAncestor, AncestorType=Window}"/>
                    </MultiBinding>
                </DataTrigger.Binding>
                <DataTrigger.Setters>
                    <Setter Property="Visibility" Value="Visible"></Setter>
                </DataTrigger.Setters>
            </DataTrigger>

            <DataTrigger Value="False">
                <DataTrigger.Binding>
                    <MultiBinding Converter="{StaticResource TrueWhenComponentIsVisible}">
                        <Binding Path="Type" />
                        <Binding Path="Dependency"/>
                        <Binding Path="SelectedType" RelativeSource="{RelativeSource FindAncestor, AncestorType=Window}"/>
                        <Binding Path="SelectedDepencency" RelativeSource="{RelativeSource FindAncestor, AncestorType=Window}"/>
                    </MultiBinding>
                </DataTrigger.Binding>
                <DataTrigger.Setters>
                    <Setter Property="Visibility" Value="Collapsed"></Setter>
                </DataTrigger.Setters>
            </DataTrigger>
        </DataTemplate.Triggers>
    </DataTemplate>

对于 Setter 属性

<Setter Property="Visibility" Value="Collapsed"></Setter>

我尝试使用绑定来获取列表框项,如下所示:

 <Setter Property="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListBoxItem}, Path=Visibility}" Value="Collapsed"></Setter>

当我尝试运行它时出现此错误,所以我认为我根本不能在那里使用绑定并需要不同的方法?

A 'Binding' cannot be set on the 'Property' property of type 'Setter'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject

【问题讨论】:

  • 我建议调查ListCollectionView。然后您的ListBox 可以使用视图作为源并在后面的代码中指定过滤器。尝试在 xaml 级别执行此操作要干净得多。
  • 在边界设置可见性有什么问题?
  • 据我所知,BindingSetter.Property 中不起作用。您必须在属性中指定静态值。
  • &lt;Setter Property="Visibility" Value="Collapsed"&gt; 相当于说myItem.Visibility = Visibility.Collapsed。您不能像这样对Visibility 属性使用绑定。
  • 嗨朱利安,我完全同意你的看法。我使用 XAML 的原因是它是类别和组件的递归列表,而 datatrigger 似乎是一种更好的方法,但我最终可能会在后面的代码中进行过滤。

标签: wpf binding listboxitem multidatatrigger


【解决方案1】:

为我工作。
不知道为什么它不适合你?

<ListBox x:Name="lb" ItemsSource="{Binding}" DisplayMemberPath="Text">
    <ListBox.Resources>
        <Style TargetType="ListBoxItem">
            <Setter Property="Visibility" Value="{Binding Path=Vis}" />
        </Style>
    </ListBox.Resources>
</ListBox>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        this.DataContext = this;
        InitializeComponent();
        List<TextVis> TextViss = new List<TextVis>();
        TextVis tv1 = new TextVis();
        tv1.Text = "tv1";
        tv1.Vis = System.Windows.Visibility.Hidden;
        TextViss.Add(tv1);
        TextVis tv2 = new TextVis();
        tv2.Text = "tv2";
        tv2.Vis = System.Windows.Visibility.Visible;
        TextViss.Add(tv2);
        lb.ItemsSource = TextViss;
    }
    public class TextVis
    {
        public string Text { get; set; }
        public Visibility Vis { get; set; }
    }
}

【讨论】:

  • 我对样式的问题是我无权访问我的 DataContext 属性。这就是我添加数据触发器的原因。如果您在上面注意到,我写了一个 IMultiValueConverter 来确定组件是否应该显示“真”或“假”
  • 你有你尝试过的代码示例吗?我会试一试!所以你可以访问 DataContext 的属性?
【解决方案2】:

我希望触发器将可见性设置为“折叠”或“可见” 父容器,即 ListBoxItem

更改ItemContainerStyle,如下所示:

<ListBox ...>
   <ListBox.ItemContainerStyle>
      <Style TargetType="ListBoxItem">
         <Style.Triggers>

             <DataTrigger Value="True">
                <DataTrigger.Binding>
                    <MultiBinding Converter="{StaticResource TrueWhenComponentIsVisible}">
                        <Binding Path="Type" />
                        <Binding Path="Dependency"/>
                        <Binding Path="SelectedType" RelativeSource="{RelativeSource FindAncestor, AncestorType=Window}"/>
                        <Binding Path="SelectedDepencency" RelativeSource="{RelativeSource FindAncestor, AncestorType=Window}"/>
                    </MultiBinding>
                </DataTrigger.Binding>

                <Setter Property="Visibility" Value="Visible"/>
            </DataTrigger>
         </Style.Triggers>
      </Style>
   </ListBox.ItemContainerStyle>
</ListBox>

顺便说一句,您真的应该创建一个合适的 ViewModel 并将所有这些逻辑移到 ViewModel 级别,而不是那么多基于 MultiBinding 和 Converter 的东西。

【讨论】:

  • 提供的代码的唯一问题是我总是在转换器中得到“DepncencyProperty.UnsetValue”,你知道为什么吗? ...是的,我最终会重构以使用 ViewModel,谢谢!
  • @gmang 我以前用 MultiBinding Converter 得到过。绑定评估没有保证的顺序,有时转换器会在设置属性之前触发。但它似乎永远不会发生在单一转换器上。测试 null 并尽可能分配。很多时候它会在绑定完成后返回到转换器。
猜你喜欢
  • 2011-06-04
  • 1970-01-01
  • 2011-05-20
  • 2011-08-11
  • 1970-01-01
  • 2013-08-10
  • 2020-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多