【问题标题】:MenuItem style through ControlTemplate in ResourceDictionary not applying correctly通过 ResourceDictionary 中的 ControlTemplate 的 MenuItem 样式未正确应用
【发布时间】:2012-01-05 07:34:56
【问题描述】:

我有一个 XAML 是这样的 Button

<Button x:Name="Button2" Style="{StaticResource User_Hyperlink_Button}" Tag="123456789.XAML" Width="86" Height="30" Margin="26,327,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Content="Button2" />

Button 的样式在 ResourceDictionary 中定义如下

<Style x:Key="User_Hyperlink_Button" TargetType="{x:Type Button}">              
  <Setter Property="Control.Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">        
        <Button Style="{DynamicResource App_button}" >
          <Hyperlink Style="{DynamicResource Button_LinkForeground}" NavigateUri="{Binding Path=Tag, RelativeSource={RelativeSource Mode=TemplatedParent, AncestorLevel=0}}">
            <InlineUIContainer>
              <TextBlock Text="{Binding Path=Content, RelativeSource={RelativeSource Mode=TemplatedParent, AncestorLevel=0}}" />
            </InlineUIContainer>
          </Hyperlink>
        </Button>
      </ControlTemplate>
    </Setter.Value>
  </Setter>     
</Style>

在这一切工作正常,但是当我对 MenuItem 执行相同操作时,MenuItem 的文本消失了。

MenuItem的xaml是这样的

<MenuItem x:Name="MenuItem1" Style="{StaticResource User_Hyperlink_MenuItem}" Tag="123456789.XAML" Header="MenuItem1" />

风格是这样的

<Style x:Key="User_Hyperlink_MenuItem" TargetType="{x:Type MenuItem}">              
  <Setter Property="Control.Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type MenuItem}">        
        <MenuItem Style="{DynamicResource App_MenuItem}"  >
          <Hyperlink Style="{DynamicResource Menu_LinkForeground}" NavigateUri="{Binding Path=Tag, RelativeSource={RelativeSource Mode=TemplatedParent, AncestorLevel=0}}">
            <InlineUIContainer>
              <TextBlock Text="{Binding Path=Header, RelativeSource={RelativeSource Mode=TemplatedParent, AncestorLevel=0}}" />
            </InlineUIContainer>
          </Hyperlink>
        </MenuItem>
      </ControlTemplate>
    </Setter.Value>
  </Setter>     
</Style>

我也这样改过风格

...
<TextBlock Text="{Binding Path=Content, RelativeSource={RelativeSource Mode=TemplatedParent, AncestorLevel=0}}" />
...

但它不起作用。 我需要通过仅修改样式来解决此问题,并且由于某些限制而无法更改 MenuItem 的 xaml。

更新 1

我需要让 MenuItem 文本出现在上面。文本在 TextBlock 中,但其值来自 MenuItem 的 Content 属性。 MenuItem 没有 Content 属性,而是具有 Items Collection,这就是文本未显示的原因。而在 Button 的情况下,链接一切正常,文本全部。

我正在处理松散的 XAML,因此我必须使用超链接进行链接。无需担心递归或继承,因为它不是问题。问题只是 MenuItem 没有 Content 属性,所以需要通过获取 Item[0] 来解决这个问题。

更新 2

我也提供其他资源供参考

<Style x:Key="App_MenuItem" TargetType="{x:Type MenuItem}">
 <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
 <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
 <Setter Property="Background" Value="#FF015DAB"/>
 <Setter Property="Foreground" Value="White"/>
 <Setter Property="Template" Value="{DynamicResource {ComponentResourceKey ResourceId=SubmenuItemTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}}"/>
 <Style.Triggers>
   <Trigger Property="Role" Value="TopLevelHeader">
     <Setter Property="Margin" Value="0,1,0,1"/>
     <Setter Property="Padding" Value="6,3,6,3"/>
     <Setter Property="Template" Value="{DynamicResource {ComponentResourceKey ResourceId=TopLevelHeaderTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}}"/>
   </Trigger>
   <Trigger Property="Role" Value="TopLevelItem">
      <Setter Property="Margin" Value="0,1,0,1"/>
      <Setter Property="Padding" Value="6,3,6,3"/>
      <Setter Property="Template" Value="{DynamicResource {ComponentResourceKey ResourceId=TopLevelItemTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}}"/>
   </Trigger>
   <Trigger Property="Role" Value="SubmenuHeader">
      <Setter Property="DockPanel.Dock" Value="Top"/>
      <Setter Property="Padding" Value="0,2,0,2"/>
      <Setter Property="Template" Value="{DynamicResource {ComponentResourceKey ResourceId=SubmenuHeaderTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}}"/>
   </Trigger>
   <Trigger Property="Role" Value="SubmenuItem">
      <Setter Property="DockPanel.Dock" Value="Top"/>
      <Setter Property="Padding" Value="0,2,0,2"/>
   </Trigger>
 </Style.Triggers>
</Style>

<Style x:Key="Menu_LinkForeground" TargetType="{x:Type Hyperlink}">
 <Setter Property="Foreground" Value="White" />
 <Setter Property="TextDecorations" Value="None" />
</Style>

【问题讨论】:

  • 你有所有的 DynamicResource 可用吗?
  • 是的,所有资源都可用。
  • 尝试用非常简单的东西代替你的 stule,比如没有绑定的 Button,看看它是否能把它捡起来。
  • 该场景对 Buttons 非常有效,但对于 MenuItem 则不起作用。
  • :) 抱歉,我的意思是 - 如果您尝试将样式应用于 MenuItem,但从 ControlTemplate 中删除所有内容,只留下一个按钮。

标签: c# wpf xaml binding


【解决方案1】:

您为 MenuItem 使用了不正确的样式。您的样式模板无法引用对象本身,因为它会创建循环引用。只需将超链接用作控件模板中的根视觉对象。

更新 1 - 我在说从使用其模板引用控件本身是行不通的。有用。它在默认模板中注入自定义内容。

这仍然没有多大意义。


这是 MenuItem 的工作版本(请注意,我从模板中删除了所有资源,因为我没有它们)。只需一一添加您的资源,看看它会在什么阶段停止工作。

<Window x:Class="WpfApplication2.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>
        <Grid.Resources>
            <Style x:Key="User_Hyperlink_MenuItem" TargetType="{x:Type MenuItem}">
                <Setter Property="Control.Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type MenuItem}">
                            <MenuItem>
                                <Button>ABC</Button>
                            </MenuItem>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Grid.Resources>
        <MenuItem Style="{StaticResource User_Hyperlink_MenuItem}">A</MenuItem>        
    </Grid>
</Window>

仅供参考,这里是默认MenuItem的样式:

<Style TargetType="{x:Type MenuItem}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib">
    <Style.Triggers>
        <Trigger Property="MenuItem.Role">
            <Setter Property="Control.Padding">
                <Setter.Value>
                    <Thickness>
                        7,2,8,3</Thickness>
                    </Setter.Value>
                </Setter>
            <Setter Property="Control.Template">
                <Setter.Value>
                    <DynamicResource ResourceKey="{ComponentResourceKey TypeInTargetAssembly=MenuItem, ResourceId=TopLevelHeaderTemplateKey}" />
                    </Setter.Value>
                </Setter>
            <Trigger.Value>
                <x:Static Member="MenuItemRole.TopLevelHeader" />
                </Trigger.Value>
            </Trigger>
        <Trigger Property="MenuItem.Role">
            <Setter Property="Control.Padding">
                <Setter.Value>
                    <Thickness>
                        7,2,8,3</Thickness>
                    </Setter.Value>
                </Setter>
            <Setter Property="Control.Template">
                <Setter.Value>
                    <DynamicResource ResourceKey="{ComponentResourceKey TypeInTargetAssembly=MenuItem, ResourceId=TopLevelItemTemplateKey}" />
                    </Setter.Value>
                </Setter>
            <Trigger.Value>
                <x:Static Member="MenuItemRole.TopLevelItem" />
                </Trigger.Value>
            </Trigger>
        <Trigger Property="MenuItem.Role">
            <Setter Property="Control.Padding">
                <Setter.Value>
                    <Thickness>
                        2,3,2,3</Thickness>
                    </Setter.Value>
                </Setter>
            <Setter Property="Control.Template">
                <Setter.Value>
                    <DynamicResource ResourceKey="{ComponentResourceKey TypeInTargetAssembly=MenuItem, ResourceId=SubmenuHeaderTemplateKey}" />
                    </Setter.Value>
                </Setter>
            <Trigger.Value>
                <x:Static Member="MenuItemRole.SubmenuHeader" />
                </Trigger.Value>
            </Trigger>
        <Trigger Property="MenuItem.Role">
            <Setter Property="Control.Padding">
                <Setter.Value>
                    <Thickness>
                        2,3,2,3</Thickness>
                    </Setter.Value>
                </Setter>
            <Trigger.Value>
                <x:Static Member="MenuItemRole.SubmenuItem" />
                </Trigger.Value>
            </Trigger>
        </Style.Triggers>
    <Style.Resources>
        <ResourceDictionary />
        </Style.Resources>
    <Setter Property="Control.HorizontalContentAlignment">
        <Setter.Value>
            <Binding Path="HorizontalContentAlignment" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ItemsControl, AncestorLevel=1}" />
            </Setter.Value>
        </Setter>
    <Setter Property="Control.VerticalContentAlignment">
        <Setter.Value>
            <Binding Path="VerticalContentAlignment" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ItemsControl, AncestorLevel=1}" />
            </Setter.Value>
        </Setter>
    <Setter Property="Panel.Background">
        <Setter.Value>
            <SolidColorBrush>
                #00FFFFFF</SolidColorBrush>
            </Setter.Value>
        </Setter>
    <Setter Property="ScrollViewer.PanningMode">
        <Setter.Value>
            <x:Static Member="PanningMode.Both" />
            </Setter.Value>
        </Setter>
    <Setter Property="Stylus.IsFlicksEnabled">
        <Setter.Value>
            <s:Boolean>
                False</s:Boolean>
            </Setter.Value>
        </Setter>
    <Setter Property="Control.Template">
        <Setter.Value>
            <DynamicResource ResourceKey="{ComponentResourceKey TypeInTargetAssembly=MenuItem, ResourceId=SubmenuItemTemplateKey}" />
            </Setter.Value>
        </Setter>
    </Style>

【讨论】:

  • 但我已经将这种参考用于按钮和标签。超链接不能用作根视觉对象,因为它不是 FrameworkElement 或派生类型。
  • @CodeMe 错了。模板不应该引用控件本身,这是没有意义的。您正在使用 Menuitem 作为备件来构建 Menuitem - 它应该如何工作?
  • 那么我该如何在 MenuItem 上应用Style="{DynamicResource App_MenuItem}" 呢?因为没有这个,文本就变得简单了。
  • 控制模板并不是真正为继承而设计的。你到底想达到什么目的?您是否让无资源示例工作?
  • 您发布的示例正在运行,但文本很简单。如果你能以某种方式在 MenuItem 上应用Style="{DynamicResource App_MenuItem}",那么问题就解决了
猜你喜欢
  • 2016-12-29
  • 1970-01-01
  • 2011-10-04
  • 2011-10-26
  • 1970-01-01
  • 2019-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多