【问题标题】:How to convert a manually created WPF Menuitem into a Template / Style Resource / Control Template如何将手动创建的 WPF Menuitem 转换为模板/样式资源/控件模板
【发布时间】:2012-10-18 13:35:01
【问题描述】:

我已经手动创建了一个 MenuItem。现在我想要它作为一个模板/样式资源/控制模板——不管这个任务最好的。

我的 MenuItem 看起来像这样(我知道短代码):

<MenuItem
x:Name="Quit"                           << OUTSIDE TEMPLATE
Command="{Binding ShutdownCommand}">    << OUTSIDE TEMPLATE
<MenuItem.Header>
    <StackPanel 
        Orientation="Horizontal">
        <TextBlock 
            Width="150" 
            Text="Quit ERD Builder"/>   << OUTSIDE TEMPLATE
        <TextBlock 
            Width="80" 
            Margin="0,2,0,0" 
            TextAlignment="Right">
            <Border 
                Padding="4,0,4,0" 
                BorderBrush="#B0B0B0" 
                Background="#fff" 
                BorderThickness="1" 
                CornerRadius="6">
                <TextBlock 
                    Width="Auto" 
                    Text="Alt+F4"       << OUTSIDE TEMPLATE
                    FontSize="10" 
                    Foreground="#555" />
            </Border>
        </TextBlock>
    </StackPanel>
</MenuItem.Header>
<MenuItem.Icon>
    <Image 
        Width="16" 
        Height="16" 
        Margin="0,0,5,0" 
        HorizontalAlignment="Center" 
        VerticalAlignment="Center" 
        RenderOptions.BitmapScalingMode="HighQuality" 
        SnapsToDevicePixels="True">
        <Image.Source>
            <BitmapImage 
                UriSource="/ERDBuilder;component/icons/bw/102-walk.png" />  << OUTSIDE TEMPLATE
        </Image.Source>
    </Image>
</MenuItem.Icon>

我用&lt;&lt; OUTSIDE TEMPLATE 声明的行是我要在MenuItem 中而不是在Template 中声明的行。

我已经尝试过一些样式,但例如“背景”出于某种原因不会工作。我可以更改“FontSize”但不能更改“背景”颜色:

<Style 
x:Key="TopTaskBarMenuitem" 
TargetType="MenuItem">
<Style.Triggers>
    <Trigger Property="IsMouseOver" Value="True">
        <Setter Property="Background" Value="#ffff00" />    << DONT WORK
        <Setter Property="FontSize" Value="20" />           << WORKS
    </Trigger>
</Style.Triggers>
<Setter Property="Foreground" Value="#000" />               << WORKS
<Setter Property="BorderThickness" Value="1" />             << WORKS
<Setter Property="Width" Value="150"/>                      << WORKS

如果我手动“XAML”,这是菜单的外观:

Manualy created Menuitem(这里不允许上传图片?!)

这是带有静态样式资源的菜单项:

Menuitem with Style Resource

如您所见,“背景”颜色不会影响菜单项。

如果我能希望我最终在“Menuitem”侧拥有这样的东西:

<MenuItem
Style="{StaticResource TopTaskBarMenuitem}"                     << TEMPLATE / STYLE BINDING
x:Name="Quit"                                                   << OUTSIDE TEMPLATE
Command="{Binding ShutdownCommand}"                             << OUTSIDE TEMPLATE
MyHeaderText="Quit ERD Builder"/>                               << OUTSIDE TEMPLATE
MyShortcutText="Alt+F4"                                         << OUTSIDE TEMPLATE
MyUriSource="/ERDBuilder;component/icons/bw/102-walk.png" />    << OUTSIDE TEMPLATE

非常感谢他们的帮助!

PS:这里的所有三个代码发布中都缺少最后一个代码行。我不知道为什么。我无法解决这个问题。

德克

【问题讨论】:

    标签: wpf xaml templates styles menuitem


    【解决方案1】:

    要获得它,您必须创建您的自己的从 MenuItem 派生的控件。

    您需要做的就是使用 DependencyProperties 创建控件类以利用其所有优点,请阅读this 了解更多信息:

    namespace MyControls
    {
        class MyMenuItem : MenuItem
        {
            public string MyHeaderText
            {
                get { return (string)GetValue(MyHeaderTextProperty); }
                set { SetValue(MyHeaderTextProperty, value); }
            }
            public static readonly DependencyProperty MyHeaderTextProperty = DependencyProperty.Register("MyHeaderText", typeof(string), typeof(MyMenuItem));
    
            public string MyShortcutText
            {
                get { return (string)GetValue(MyShortcutTextProperty); }
                set { SetValue(MyShortcutTextProperty, value); }
            }
            public static readonly DependencyProperty MyShortcutTextProperty = DependencyProperty.Register("MyShortcutText", typeof(string), typeof(MyMenuItem));
    
            public string MyUriSource
            {
                get { return (string)GetValue(MyUriSourceProperty); }
                set { SetValue(MyUriSourceProperty, value); }
            }
            public static readonly DependencyProperty MyUriSourceProperty = DependencyProperty.Register("MyUriSource", typeof(string), typeof(MyMenuItem));
        }
    }
    

    现在您可以实例化您的控件,但您仍需要“重新模板化”它:

    <mc:MyMenuItem MyHeaderText="Quit ERD Builder" MyShortcutText="Alt+F4" MyUriSource="/ERDBuilder;component/icons/bw/102-walk.png">
        <mc:MyMenuItem.Style>
            <Style TargetType="mc:MyMenuItem">
                <Style.Setters>
                    <Setter Property="HeaderTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Width="150" Text="{Binding Mode=TwoWay, Path=MyHeaderText, RelativeSource={RelativeSource FindAncestor, AncestorType=mc:MyMenuItem}}"/>
                                    <TextBlock Width="80" Margin="0,2,0,0" TextAlignment="Right">
                                        <Border Padding="4,0,4,0" BorderBrush="#B0B0B0" Background="#fff" BorderThickness="1" CornerRadius="6">
                                            <TextBlock Width="Auto" Text="{Binding Mode=TwoWay, Path=MyShortcutText, RelativeSource={RelativeSource FindAncestor, AncestorType=mc:MyMenuItem}}" FontSize="10" Foreground="#555" />
                                        </Border>
                                    </TextBlock>
                                </StackPanel>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="Icon">
                        <Setter.Value>
                            <Image Width="16" Height="16" Margin="0,0,5,0" HorizontalAlignment="Center" VerticalAlignment="Center" RenderOptions.BitmapScalingMode="HighQuality" SnapsToDevicePixels="True" Source="{Binding Mode=OneWay, Path=MyUriSource, RelativeSource={RelativeSource FindAncestor, AncestorType=mc:MyMenuItem}}" />
                        </Setter.Value>
                    </Setter>
                </Style.Setters>
            </Style>
        </mc:MyMenuItem.Style>
    </mc:MyMenuItem>
    

    别忘了在你的窗口(或者你可以放置这个控件的任何地方)标签中引用这个新控件的命名空间:

    xmlns:mc="clr-namespace:MyControls"
    

    可以在 ResourceDictionary 中插入此样式,这样您就无需在每次使用此控件时都引用它。

    <Style TargetType="mc:MyMenuItem">
        <!-- Style comes here -->
    </Style>
    

    那么你就可以得到你所问的:

    <mc:MyMenuItem MyHeaderText="Quit ERD Builder" MyShortcutText="Alt+F4" MyUriSource="/ERDBuilder;component/icons/bw/102-walk.png" />
    

    希望对你有帮助!

    【讨论】:

    • 嗨,威利。非常感谢!这很有帮助。
    • 嗨,威利。我试过了,我认为它工作得很好。但是图标的 URI 不起作用。编译后出现错误:XmlParseException: System.Windows.Media.Imaging.BitmapImage" has raise an Exception.
    【解决方案2】:

    CoreStyle.xaml

    来自模板/样式的部分:

    <Setter Property="Icon">
      <Setter.Value>
        <ctrl:Bitmap>
          <ctrl:Bitmap.Source>
            <!-- This doesnt work: --> <BitmapImage UriSource="{Binding Mode=OneWay, Path=MenuIcon, RelativeSource={RelativeSource FindAncestor, AncestorType=ctrl:MainMenuItem}}" />
            <!-- This Still works fine: <BitmapImage UriSource="../Resources/Icons/16/page_add.png" />-->
          </ctrl:Bitmap.Source>
        </ctrl:Bitmap>
      </Setter.Value>
    </Setter>
    

    MainMenuItem.cs

    从 MenuItem 派生的自定义控件类:

    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    
    namespace ErdBuilder.Shell.Controls
    {
    class MainMenuItem : MenuItem
    {
        public ICommand MenuCommand
        {
            get { return (ICommand) GetValue(MenuCommandProperty); }
            set { SetValue(MenuCommandProperty, value); }
        }
    
        public static readonly DependencyProperty MenuCommandProperty = DependencyProperty.Register("MenuCommand", typeof(ICommand), typeof(MainMenuItem));
    
        public string MenuText
        {
            get { return (string)GetValue(MenuTextProperty); }
            set { SetValue(MenuTextProperty, value); }
        }
    
        public static readonly DependencyProperty MenuTextProperty = DependencyProperty.Register("MenuText", typeof(string), typeof(MainMenuItem));
    
        public string MenuShortcut
        {
            get { return (string)GetValue(MenuShortcutProperty); }
            set { SetValue(MenuShortcutProperty, value); }
        }
    
        public static readonly DependencyProperty MenuShortcutProperty = DependencyProperty.Register("MenuShortcut", typeof(string), typeof(MainMenuItem));
    
        public string MenuIcon
        {
            get { return (string)GetValue(MenuIconProperty); }
            set { SetValue(MenuIconProperty, value); }
        }
    
        public static readonly DependencyProperty MenuIconProperty = DependencyProperty.Register("MenuIcon", typeof(string), typeof(MainMenuItem));
    
    }
    

    }

    我也试过这个:

    public BitmapImage MenuIcon
        {
            get { return new BitmapImage(new Uri((string)GetValue(MenuIconProperty))); }
            set { SetValue(MenuIconProperty, value); }
        }
    
        public static readonly DependencyProperty MenuIconProperty =     DependencyProperty.Register("MenuIcon", typeof(BitmapImage), typeof(MainMenuItem));
    

    Shell.xaml

    最后是我尝试使用新控件的部分:

    <ctrl:MainMenuItem x:Name="TestMenu"
      MenuCommand="{x:Static ApplicationCommands.New}"
      MenuText="New..."
      MenuShortcut="Ctr+N"
      MenuIcon="../Resources/Icons/16/page_add.png"/>
    

    【讨论】:

    • MenuCommand 属性也不起作用。我可以设置它并且没有错误,但它无法识别我的 MenuCommand 值设置。
    猜你喜欢
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    相关资源
    最近更新 更多