昨天要做一个ListView的右键菜单,需要根据listView绑定的集合中每个对象里的一个bool属性来决定是否显示该项的右键菜单,经过不懈的尝试和努力,最终实现了两种方案,一种是当该值为false时,可以点出右键菜单,但菜单项置灰不可选;另一种就是直接不出来菜单,右击没反应。下面是第一种方案:
<ListView x:Name="ServerList" ItemsSource="{Binding Path=Servers}"> <ListView.Resources > <Style x:Key="CheckMenuItem" TargetType="{x:Type MenuItem}"> <Style.Triggers> <DataTrigger Binding="{Binding Path=IsLogin, Converter={StaticResource Bool2String}}" Value="True"> <Setter Property="IsEnabled" Value="False"/> </DataTrigger> </Style.Triggers> </Style> <ContextMenu x:Key="ContextMenuItem"> <MenuItem Header="play with her" Style="{StaticResource CheckMenuItem}"/> <MenuItem Header="kiss her" Style="{StaticResource CheckMenuItem}"/> </ContextMenu> </ListView.Resources> <ListView.ItemContainerStyle> <Style TargetType="{x:Type ListViewItem}"> <Setter Property="ContextMenu" Value="{StaticResource ContextMenuItem}"/> </Style> </ListView.ItemContainerStyle> <ListView.View> <GridView> <GridViewColumn Header="服务器" Width="485" DisplayMemberBinding="{Binding ServerName}"/> </GridView> </ListView.View> </ListView>
在这段代码中,数据源servers是一个ObservableCollection<ServerViewModel>类型,而dataTrigger中绑定的变量IsLogin是ServerViewModel中的一个bool属性,用它来决定listView中某一项的右键菜单是否可用。
第二种方案:
<ListView x:Name="listView" HorizontalAlignment="Left" Height="100" Margin="9,82,0,0" VerticalAlignment="Top" Width="auto" ItemsSource="{Binding Path=Servers}"> <ListView.Resources> <ContextMenu x:Key="ct"> <MenuItem Header="play with her" /> <MenuItem Header="kiss her" /> </ContextMenu> </ListView.Resources> <ListView.ItemContainerStyle> <Style TargetType="{x:Type ListViewItem}"> <Setter Property="ContextMenu" Value="{StaticResource ct}"></Setter> <Style.Triggers> <DataTrigger Binding="{Binding Path=IsLogin, Converter={StaticResource bool2string}}" Value="True"> <Setter Property="ContextMenuService.IsEnabled" Value="False"/> </DataTrigger> </Style.Triggers> </Style> </ListView.ItemContainerStyle> <ListView.View> <GridView> <GridViewColumn Header="header" Width="485" DisplayMemberBinding="{Binding ServerName}"/> </GridView> </ListView.View> </ListView>
这个方法和上一个不同的地方在于上一个方法是根据条件改变右键菜单(ContextMenu)里的项(MenuItem)的状态,可用或者不可用,而这个方法是根据条件决定ListView里的每一项(ListViewItem)是否显示右键菜单,就是修改ContextMenuService.IsEnabled的值。
另外再给大家分享一下我之前尝试失败的方法,大家参考一下,第一种:
<ListView.Resources> <Style x:Key="CheckContextMenu" TargetType="{x:Type ContextMenu}"> <Style.Triggers> <DataTrigger Binding="{Binding Path=IsLogin, Converter={StaticResource bool2string}}" Value="True"> <Setter Property="Visibility" Value="Collapsed"/> </DataTrigger> </Style.Triggers> </Style> <ContextMenu x:Key="ct" Style="{StaticResource CheckContextMenu}"> <MenuItem Header="play with her" /> <MenuItem Header="kiss her" /> </ContextMenu> </ListView.Resources>
就是在resoures里给contextMenu加style,这种方式实现出来有bug, 就是当点击允许显示菜单的项时没有问题,当点击不允许显示菜单的项时也不会显示菜单,但是点击了不允许显示菜单的项之后再去点击允许显示菜单的项时,显示的菜单是上一个本来不允许显示菜单的项的菜单。这是什么原因造成的我也没去研究。
第二种:
<ListView.Style> <Style> <Style.Triggers> <DataTrigger Binding="{Binding SelectedItem.IsLogin}" Value="True"> <Setter Property="ContextMenuService.IsEnabled" Value="True"/> </DataTrigger> </Style.Triggers> </Style> </ListView.Style>
这样子也是行不通的。
好的,今天就写到这里,周六下午来公司写blog,写完感觉蛮充实的,时间没有浪费,晚上去看电影哇卡卡卡卡卡