WPF:上下文菜单项中的两列

时间:2017-03-04 19:40:09

标签: c# wpf contextmenu datatemplate itemtemplate

我正在尝试创建一个包含两列的上下文菜单:

Context Menu

项目的文本绑定了项目的Name属性,快捷键绑定到GestureText属性。但是,似乎没有遵守列定义,我看到了这一点:enter image description here

我的XAML如下:

<Window x:Class="ContextMenu2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid Margin="0,2,0.4,-2.2">
        <TextBlock Text="RightClickMe" HorizontalAlignment="Left" VerticalAlignment="Top">
            <TextBlock.ContextMenu>
                <ContextMenu ItemsSource="{Binding Items}">
                    <ContextMenu.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="50*"/>
                                    <ColumnDefinition Width="70*"/>
                                </Grid.ColumnDefinitions>
                                <TextBlock Grid.Column="0" Text="{Binding Name}" />
                                <TextBlock Grid.Column="1" Text="{Binding GestureText}"/>
                            </Grid>
                        </DataTemplate>
                    </ContextMenu.ItemTemplate>
                </ContextMenu>
            </TextBlock.ContextMenu>
        </TextBlock>
    </Grid>
</Window>

C#

using System;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Windows;
using System.Windows.Input;

namespace ContextMenu2
{
    public class CMenu
    {
        public String Name { get; set; }
        public string GestureText { get; set; }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        public  ObservableCollection<CMenu> Items { get; set; }= new ObservableCollection<CMenu>
        {
            new CMenu()
            {
                Name = "Press me",
                GestureText =
                    new KeyGesture(Key.Q, ModifierKeys.Control).GetDisplayStringForCulture(CultureInfo.CurrentUICulture)
            },
            new CMenu()
            {
                Name = "Press me too",
                GestureText =
                    new KeyGesture(Key.R, ModifierKeys.Control).GetDisplayStringForCulture(CultureInfo.CurrentUICulture)
            }
        };
    }
}

这里有什么问题?

3 个答案:

答案 0 :(得分:1)

您可以将InputGestureText中的ItemContainerStyle绑定到GestureText

<ContextMenu ItemsSource="{Binding Items}" HorizontalContentAlignment="Stretch">
    <ContextMenu.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}" />
        </DataTemplate>
    </ContextMenu.ItemTemplate>
    <ContextMenu.ItemContainerStyle>
        <Style TargetType="MenuItem">
            <Setter Property="InputGestureText" Value="{Binding GestureText}"/>
        </Style>
    </ContextMenu.ItemContainerStyle>
</ContextMenu>

另请注意,设置HorizontalAlighnmentHorizontalContentAlignment无济于事。请注意default style:

的这一部分
<Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto"
                        SharedSizeGroup="Icon" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="Auto"
                        SharedSizeGroup="Shortcut" />
    <ColumnDefinition Width="13" />
</Grid.ColumnDefinitions>

以及第三列中TextBlock的边距Margin="5,2,2,2"

答案 1 :(得分:0)

我没有对此进行过测试,但我的猜测是包含列的MenuItem不会占用整个宽度(它们可能是左对齐的)。因此,可以尝试使用例如像这样的东西:

<ContextMenu.ItemContainerStyle>
    <Style TargetType="{x:Type MenuItem}">
        <Setter Property="HorizontalAlignment" Value="Stretch"/>
    </Style>
</ContextMenu.ItemContainerStyle>

答案 2 :(得分:0)

如果您真的想要创建自定义ContextMenu,则需要覆盖ControlTemplate ItemContainer的MenuItem,即在Grid中定义ControlTemplate而不是在这个而不是在ContextMenu的ItemTemplate中:

<TextBlock Text="RightClickMe" HorizontalAlignment="Left" VerticalAlignment="Top">
    <TextBlock.ContextMenu>
        <ContextMenu ItemsSource="{Binding Items}">
            <ContextMenu.ItemContainerStyle>
                <Style TargetType="MenuItem">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type MenuItem}">
                                <Border x:Name="templateRoot" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                                    <Grid Margin="-1">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition MinWidth="22" SharedSizeGroup="MenuItemIconColumnGroup" Width="Auto"/>
                                            <ColumnDefinition Width="13"/>
                                            <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="5*" SharedSizeGroup="a"/>
                                            <ColumnDefinition SharedSizeGroup="MenuItemIGTColumnGroup" Width="Auto"/>
                                            <ColumnDefinition Width="7*" SharedSizeGroup="b"/>
                                        </Grid.ColumnDefinitions>
                                        <ContentPresenter x:Name="Icon" Content="{TemplateBinding Icon}" ContentSource="Icon" HorizontalAlignment="Center" Height="16" Margin="3" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" Width="16"/>
                                        <Border x:Name="GlyphPanel" BorderBrush="#FF26A0DA" BorderThickness="1" Background="#3D26A0DA" ClipToBounds="False" HorizontalAlignment="Center" Height="22" Margin="-1,0,0,0" Visibility="Hidden" VerticalAlignment="Center" Width="22">
                                            <Path x:Name="Glyph" Data="F1M10,1.2L4.7,9.1 4.5,9.1 0,5.2 1.3,3.5 4.3,6.1 8.3,0 10,1.2z" Fill="#FF212121" FlowDirection="LeftToRight" Height="11" Width="10"/>
                                        </Border>
                                        <ContentPresenter x:Name="menuHeaderContainer" ContentTemplate="{TemplateBinding HeaderTemplate}" 
                                                                      Content="{Binding Name}" Grid.Column="2" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" HorizontalAlignment="Left" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>
                                        <TextBlock x:Name="menuGestureText" Grid.Column="4" Margin="{TemplateBinding Padding}" 
                                                               Text="{Binding GestureText}" VerticalAlignment="Center" HorizontalAlignment="Right"/>
                                    </Grid>
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="Icon" Value="{x:Null}">
                                        <Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
                                    </Trigger>
                                    <Trigger Property="IsChecked" Value="True">
                                        <Setter Property="Visibility" TargetName="GlyphPanel" Value="Visible"/>
                                        <Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
                                    </Trigger>
                                    <Trigger Property="IsHighlighted" Value="True">
                                        <Setter Property="Background" TargetName="templateRoot" Value="#3D26A0DA"/>
                                        <Setter Property="BorderBrush" TargetName="templateRoot" Value="#FF26A0DA"/>
                                    </Trigger>
                                    <Trigger Property="IsEnabled" Value="False">
                                        <Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="#FF707070"/>
                                        <Setter Property="Fill" TargetName="Glyph" Value="#FF707070"/>
                                    </Trigger>
                                    <MultiTrigger>
                                        <MultiTrigger.Conditions>
                                            <Condition Property="IsHighlighted" Value="True"/>
                                            <Condition Property="IsEnabled" Value="False"/>
                                        </MultiTrigger.Conditions>
                                        <Setter Property="Background" TargetName="templateRoot" Value="#0A000000"/>
                                        <Setter Property="BorderBrush" TargetName="templateRoot" Value="#21000000"/>
                                    </MultiTrigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ContextMenu.ItemContainerStyle>
        </ContextMenu>
    </TextBlock.ContextMenu>
</TextBlock>

如果您只想将InputGestureText属性绑定到GestureText属性,则应参考@ Ron的答案。