WPF如何在列表中给弹出菜单ContextMenu指定不一样的数据上下文DataContext

我们在使用WPF中的ListView之类的列表控件的时候,里面的ListViewItem的DataContext是列表中的项目,跟ListView控件的DataContext不一样。
有时候(比如权限相关的控制等)我们如果希望ContextMenu的菜单项的IsEnable等属性能跟列表项目之外的实例的属性绑定,则需要单独指定这个属性绑定的不一样的DataContext,同时又不改动整个ContextMenu的DataContext,这里举一例,需要.NET 4.0及以上。
例子中有一个UserControl,我把它命名为_this,同时指定它的DataContext为_this。其内有一个ListView,

<UserControl x:Class="Design_Library.ControlDesigns"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Design_Library" 
             mc:Ignorable="d" 
             x:Name="_this"
             DataContext="{Binding ElementName=_this}"

......此处省略N多字......

    <UserControl.Resources>
        <!--#region ContextMenu for Design -->
        <ContextMenu x:Key="DesignCtxMenu">
            <MenuItem Header="_Edit" IsEnabled="{Binding HasDesignEditingPermission, Source={x:Reference _this}}" Click="btnEditDsgn_Click"/>
            <MenuItem Header="_Delete" IsEnabled="{Binding HasDesignRemovingPermission, Source={x:Reference _this}}" Click="btnDeleteDsgn_Click"/>
        </ContextMenu>
        <!--#endregion-->
    </UserControl.Resources>

......此处省略N多字......

            <ListView x:Name="lvDesigns" ItemsSource="{Binding Path=Designs}" SelectedItem="{Binding Path=SelectedDesign}" SelectionMode="Single" d:ItemsSource="{d:SampleData ItemCount=5}">
                <ListView.ItemContainerStyle>
                    <Style TargetType="{x:Type ListViewItem}">
                        <!--<EventSetter Event="PreviewMouseLeftButtonDown" Handler="OnListViewItem_PreviewMouseLeftButtonDown" />-->
                        <EventSetter Event="MouseDoubleClick" Handler="ListViewItem_MouseDoubleClick"/>
                        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    </Style>
                </ListView.ItemContainerStyle>
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <Grid x:Name="panelDesign" ToolTip="{Binding Path=UICode}" Background="{Binding Path=DisabilityIndicator}">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100"/>
                                <ColumnDefinition Width="3"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <Image x:Name="imgDesign" Source="{Binding Path=Thumbnail}" Width="100" Height="100" ></Image>

                            <StackPanel Grid.Column="2">
                                <TextBlock FontWeight="UltraBold" Foreground="White" Background="DarkGoldenrod" Margin="0,5,0,0" Text="{Binding Path=UICode}"/>
                                <TextBlock FontWeight="Bold" Foreground="White" Background="DarkGoldenrod" Margin="0,0,0,5" Text="{Binding Path=Collection.UICode}" />
                                <TextBlock Text="{Binding Path=Designer.UIDisplay, StringFormat=Designer: {0}}" ToolTip="{Binding Path=Designer.UICombinedDisplay}" />
                                <TextBlock x:Name="txtDesignDate" Text="{Binding Path=UIDesignDate, StringFormat={}{0:d}}" />
                                <TextBlock Text="{Binding Path=UIDescription}" Height="{Binding ElementName=txtDesignDate, Path=ActualHeight}" Width="{Binding ElementName=txtDesignDate , Path=ActualWidth}" ToolTip="{Binding Path=UIDescription}" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" />
                            </StackPanel>

                            <Grid.ContextMenu>
                                <StaticResource ResourceKey ="DesignCtxMenu"/>
                            </Grid.ContextMenu>
                        </Grid>
                    </DataTemplate>
                </ListView.ItemTemplate>

            </ListView>

重点如下:

  1. 第8行和第9行定义了这个UserControl的数据上下文是它本身
             x:Name="_this"
             DataContext="{Binding ElementName=_this}"

注意定义数据上下文的时候还能用下面的方式,这里不适用,因为这种方式需要一个明确的x:Name

             DataContext="{Binding RelativeSource={RelativeSource Self}}"
  1. 弹出菜单的资源的定义
<UserControl.Resources>
    <!--#region ContextMenu for Design -->
    <ContextMenu x:Key="DesignCtxMenu">
        <MenuItem Header="_Edit" IsEnabled="{Binding HasDesignEditingPermission, Source={x:Reference _this}}" Click="btnEditDsgn_Click"/>
        <MenuItem Header="_Delete" IsEnabled="{Binding HasDesignRemovingPermission, Source={x:Reference _this}}" Click="btnDeleteDsgn_Click"/>
    </ContextMenu>
    <!--#endregion-->
  1. 在ListView的数据模板里引用弹出菜单资源,这里不能直接把弹出菜单定义在这里,一定要用静态资源的方式,不然编辑器会提示找不到_this的定义,但不影响运行时,也就是说错误提示只在编辑器里提示,不影响最终程序的运行。

                            <Grid.ContextMenu>
                                <StaticResource ResourceKey ="DesignCtxMenu"/>
                            </Grid.ContextMenu>
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容