【问题标题】:Custom WPF context menu with text on top顶部带有文本的自定义 WPF 上下文菜单
【发布时间】:2016-01-18 10:48:34
【问题描述】:

我创建了一个自定义上下文菜单模板,如下所示:

<Style TargetType="{x:Type ContextMenu}">
            <Setter Property="Background" Value="{StaticResource menuBorderBrush}"/>
            <Setter Property="Foreground" Value="{StaticResource menuForegroundBrush}"/>
            <Setter Property="FontSize" Value="13"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ContextMenu}">
                        <Border x:Name="Border" Background="{StaticResource menuBackgroundBrush}" BorderThickness="5" BorderBrush="{StaticResource menuBackgroundBrush}">
                            <StackPanel>
                                <TextBlock TextAlignment="Center" Padding="5,5,5,10">
                                    You are not logged in.
                                </TextBlock>
                                <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle" />
                            </StackPanel>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

现在我希望能够更改“您尚未登录”。以编程方式文本。我尝试从创建一个继承自 ContextMenu 的自定义控件类开始,并将 XAML 中的 x:Type 更改为此类,但随后属性(如背景、前景等)是未知的。

如果不从头实现新的 ContextMenu,我该如何做到这一点?

【问题讨论】:

    标签: c# wpf xaml


    【解决方案1】:

    您可以为此添加TextBlock BindingTemplatedParent

    <TextBlock TextAlignment="Center" Padding="5,5,5,10"
               Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Tag}" />
    

    然后将文本添加到 ContextMenu Tag 属性中,就像这样。

    <Grid.ContextMenu>
        <ContextMenu Tag="Test menuItem text" />
    </Grid.ContextMenu>
    

    更新

    有一些技巧可以传递许多属性。例如,您可以将 ContextMenu 绑定到具有许多属性的 viewModel。视图模型应该具有实现INotifyPropertyChanged 行为。所以你可以写这样的东西,但是有很多属性。

    public class OwnObject : INotifyPropertyChanged
    {
        private string _text;
    
        public string Text
        {
            get { return _text; }
            set { _text = value; NotifyPropertyChanged( "Text" ); }
        }
    
        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion
        protected void NotifyPropertyChanged( String info )
        {
            if ( PropertyChanged != null )
            {
                PropertyChanged( this, new PropertyChangedEventArgs( info ) );
            }
        }
    }
    

    并通过Tag 属性传递这个viewModel 对象。

    <Grid.ContextMenu>
        <ContextMenu Tag="{Binding Object}" />
    </Grid.ContextMenu>
    

    并通过Tag.Text在菜单Style中使用它。

    <TextBlock TextAlignment="Center" Padding="5,5,5,10"
         Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Tag.Text}" />
    

    【讨论】:

    • 这有效,但仅适用于一个属性。 (因为我们使用的是已经定义的“Tag”属性)是否还有针对任意数量属性的解决方案?
    • 是的,有可能,我已经更新了答案。此外,如果您愿意,您可以通过 Tag 属性传递 ObservableCollection
    • 工作正常,谢谢! IsIdChanged = true; 据我所知没有任何用途?
    • 是的,它没有。它来自其他代码示例,我删除了这个以避免误解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多