简体   繁体   English

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

[英]WPF: Two Columns in Context Menu Item

I am trying to create a context menu with two columns like this: 我正在尝试创建具有两列的上下文菜单,如下所示:

上下文菜单

The text of the item is bound the Name property of the item and the shortcut key is bound to the GestureText property. 项目的文本绑定到项目的Name属性,快捷键绑定到GestureText属性。 However, the column definitions do not seem to be obeyed and I see this: 但是,似乎没有遵守列定义,我看到了这一点: 在此处输入图片说明

My XAML is as follows: 我的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# 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)
            }
        };
    }
}

What's wrong here? 怎么了

You can bind InputGestureText in ItemContainerStyle to GestureText : 您可以将ItemContainerStyle InputGestureText绑定到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>

Also note that setting HorizontalAlighnment or HorizontalContentAlignment is not going to help. 另请注意,设置HorizontalAlighnmentHorizontalContentAlignment不会有帮助。 Please note this part of the default style: 请注意默认样式的这一部分

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto"
                        SharedSizeGroup="Icon" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="Auto"
                        SharedSizeGroup="Shortcut" />
    <ColumnDefinition Width="13" />
</Grid.ColumnDefinitions>

and the margin of the TextBlock in the third column which is Margin="5,2,2,2" . 第三列中的TextBlock的边距为Margin="5,2,2,2"

I haven't tested this, but my guess would be that the MenuItems that contain your columns are not taking up the full width themselves (they are probably left aligned). 我没有测试过,但是我猜想是包含您的列的MenuItems本身并没有占据整个宽度(它们可能保持对齐)。 So maybe try changing their alignment using , eg something like this: 因此,也许尝试使用来更改其对齐方式,例如:

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

If you really want to create a custom looking ContextMenu you need to override the ControlTemplate of the MenuItem ItemContainer, ie define your Grid in the ControlTemplate instead of this one instead of in the ItemTemplate of the ContextMenu: 如果您确实想创建自定义外观的ContextMenu ,则需要覆盖MenuItem ItemContainer的ControlTemplate ,即在ControlTemplate而不是在ContextMenu的ItemTemplate中定义此Grid

<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>

If you simply want to bind the InputGestureText property to your GestureText property you should refer to @Ron's answer. 如果只想将InputGestureText属性绑定到GestureText属性,则应参考GestureText的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM