【问题标题】:Access Property of object bound to ItemsSource绑定到 ItemsSource 的对象的访问属性
【发布时间】:2016-12-15 16:08:50
【问题描述】:

我在 WPF 中有以下 MenuItem:

<MenuItem 
    x:Name="Menu1" 
    ItemsSource="{Binding ListOfObject1}" Visibility="{Binding ListOfObject1, Converter={u:NullToVisibleConverter}}"
    >
    <MenuItem.Style>
        <Style>
            <Setter 
                Property="Control.IsEnabled" 
                Value="true"
                />
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition 
                            Binding="{Binding PropertyInViewModel, Converter={baseTc:IsNullConverter} }" 
                            Value="true"
                            />
                        <Condition 
                            Binding="{Binding ElementName=Menu1, Path=Items.BoolInObject1}" 
                            Value="True"
                            />
                    </MultiDataTrigger.Conditions>
                    <Setter 
                        Property="Control.IsEnabled" 
                        Value="False"
                        />
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    </MenuItem.Style>
</MenuItem>

所以如果属性PropertyInViewModel 为空并且属性BoolInObject1 为真,我希望我的MenuItem 为IsEnabled=false。 DataContext 设置为 ViewModel。对象Object1 在别处定义。所以基本上我的第二个条件不起作用,即我需要从 itemssource 访问项目/对象的属性以检查该项目是否启用。 有人可以解释一下我该怎么做吗?那么如何定义第二个条件以访问绑定到 ItemsSource 的对象的属性。 提前致谢。

【问题讨论】:

  • 顺便说一句,如果这些是唯一的条件,您可以添加一个 Setter 以默认禁用,然后添加两个单绑定 DataTriggers:一个启用如果 PropertyInViewModel 不是 {x:Null} , 如果whatnot.BoolInObject1 为假,则启用。以这种方式获得相同的布尔结果。
  • 它是多数据触发器而不是多绑定,我认为我不需要多转换器,因为我已经指定了条件,是吗? Object1 是一个公共类,在我的解决方案中定义。所以当然它是由 ListOfObject1 引用的,即它是列表的类型。
  • 哎呀,你是对的。无需多路转换器。
  • 等一下,这里的目标是什么?此 MenuItem 是具有多个子菜单项的父项,Items 中的每个项对应一个。您想根据视图模型的某些属性启用/禁用父级,...其中一个子级的某些属性?哪个孩子?还是全部?
  • 好吧,也许这就是问题所在。我想根据属性禁用子项(itemssources 对象)。如果列表为空,则父级将不可见。我以为孩子会继承样式,而父母没有 boolinobject1 属性,但这可能是错误的......

标签: wpf mvvm binding


【解决方案1】:

子菜单项不会继承 Style。将Style 应用于子菜单项的方式是通过MenuItem.ItemContainerStyle,就像ListBoxListView 一样;所有这些类都从ItemsControl 以及ItemsSource 属性和其他一些属性继承该属性。

每个子菜单项将有一个ListOfObject1 项用于DataContext,因此绑定BoolInObject1 很容易。绑定PropertyInViewModel 更难,因为视图模型不会是DataContext。但是,它是父 MenuItemDataContext,您可以使用 {RelativeSource AncestorType=MenuItem} 通过可视树访问它。

我还为子菜单项的Header 属性添加了一个setter;您自然需要更改绑定的属性。我将TargetType 添加到您的Style

<MenuItem 
    x:Name="Menu1" 
    ItemsSource="{Binding ListOfObject1}" 
    Visibility="{Binding ListOfObject1, Converter={u:NullToVisibleConverter}}"
    >
    <MenuItem.ItemContainerStyle>
        <Style TargetType="MenuItem">
            <Setter 
                Property="IsEnabled" 
                Value="true"
                />
            <Setter 
                Property="Header" 
                Value="{Binding SomePropertyOfItemClass}"
                />
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition 
                            Binding="{Binding PropertyInViewModel, Converter={baseTc:IsNullConverter}, RelativeSource={RelativeSource AncestorType=MenuItem}}" 
                            Value="true"
                            />
                        <Condition 
                            Binding="{Binding BoolInObject1}" 
                            Value="True"
                            />
                    </MultiDataTrigger.Conditions>
                    <Setter 
                        Property="IsEnabled" 
                        Value="False"
                        />
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    </MenuItem.ItemContainerStyle>
</MenuItem>

【讨论】:

  • 谢谢,看起来很有希望。我会尽快检查并标记您的答案。谢谢,这花了我很多时间。
  • 那么这个relativesource祖先,它具体是做什么的呢?是否将datacontext设置为祖先的datacontext?
  • @SQLStarter 总之,不。这意味着它不是去DataContext 寻找Path 指定的属性,而是去祖先那里寻找它。如果它改变了无法工作的MenuItemDataContext - 你有两个Bindings 这里有两个不同的来源;哪个会赢?
  • 所以它奏效了。只有我必须使用&lt;Condition "{Binding ElementName=MyWindowName}", Path=PropertyInViewModel}" 而不是RelativeSource。我想这是因为我说过,DataContext 是 ViewModel,但可能这是 Windows DataContext。非常感谢!
  • @SQLStarter 你是说你把窗口变成了它自己的DataContext?不是个好主意。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-26
  • 1970-01-01
  • 2018-08-27
  • 2012-01-08
  • 1970-01-01
  • 2013-03-14
相关资源
最近更新 更多