2009-02-05 43 views
10

¿Alguien sabe cómo cambiar el pincel para el fondo de un menú? Esto suena simple, pero no veo ninguna manera obvia de hacer esto. Pensarías que la propiedad Background lo cambiaría, pero no es así.WPF C# - Cambiar el pincel del fondo de un menú

Esto es lo que mi menú se parece a (nótese el fondo blanco por defecto):

Ejemplo de código:

<Window x:Class="WpfApplication1.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Window1" Height="300" Width="300"> 

<Window.Resources> 
    <SolidColorBrush x:Key="menuItemBrush" 
        Color="#FF505050" /> 
</Window.Resources> 

<Grid x:Name="mainGrid" 
     Background="#FF252525"> 

    <Menu x:Name="mainMenu" 
      Background="{DynamicResource menuItemBrush}" 
      Grid.ColumnSpan="2" 
      VerticalAlignment="Top"> 

     <MenuItem x:Name="fileMenu" 
        Background="{DynamicResource menuItemBrush}" 
        Foreground="White" 
        Header="File"> 

      <MenuItem x:Name="fileOpenMenuItem" 
         Background="{DynamicResource menuItemBrush}" 
         Foreground="White" 
         Header="Open..." /> 

      <MenuItem x:Name="fileSaveMenuItem" 
         Background="{DynamicResource menuItemBrush}" 
         Foreground="White" 
         Header="Save" /> 

      <MenuItem x:Name="fileSaveAsMenuItem" 
         Background="{DynamicResource menuItemBrush}" 
         Foreground="White" 
         Header="Save As..." /> 

      <Separator Style="{DynamicResource menuItemSeperator}" /> 

      <MenuItem x:Name="fileExitMenuItem" 
         Background="{DynamicResource menuItemBrush}" 
         Foreground="White" 
         Header="Exit" /> 
     </MenuItem> 
    </Menu> 
</Grid> 

+1

Este artículo parece útil. Muestra cómo personalizar las plantillas de control de elementos (a diferencia de los estilos en la respuesta de Nate): http://blogs.microsoft.co.il/blogs/pavely/archive/2010/10/01/wpf-menu-customization.aspx –

+2

¿Por qué no cargaste la imagen a stackoverflow? No está disponible ahora. – Tara

Respuesta

11

Sugiero usar una herramienta llamada kaxaml para escribir estilos. Incluye varios fragmentos de código, un selector de color y una buena manera de ver al instante qué cambios en el código xaml hace. Aquí hay un estilo de menú completo para lo que estás tratando de hacer. Simplemente cambie los colores del pincel en la parte superior para que se adapte a sus necesidades.

<Page 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <Page.Resources> 

    <!--************************** 
    * STYLE: MenuItem 
    ************************** --> 
    <SolidColorBrush x:Key="HighlightedBackgroundBrush" Color="#FF797878" /> 
    <SolidColorBrush x:Key="MenuBackgroundBrush" Color="#FF505050" /> 
    <SolidColorBrush x:Key="NormalBorderBrush" Color="#FFFFFFFF" /> 
    <SolidColorBrush x:Key="SolidMenuFontBrush" Color="#FFFFFFFF" /> 
    <SolidColorBrush x:Key="HighlightedText" Color="#FFFFFFFF" /> 
    <Style x:Key="{x:Type Menu}" TargetType="{x:Type Menu}"> 
    <Setter Property="OverridesDefaultStyle" Value="True"/> 
    <Setter Property="SnapsToDevicePixels" Value="True"/> 
    <Setter Property="Height" Value="25"/> 
    <Setter Property="Foreground" Value="{StaticResource SolidMenuFontBrush}"/> 
    <Setter Property="Template"> 
     <Setter.Value> 
     <ControlTemplate TargetType="{x:Type Menu}"> 
      <Border 
      Background="{StaticResource MenuBackgroundBrush}" 
      BorderBrush="{StaticResource MenuBackgroundBrush}" 
      BorderThickness="1"> 
      <StackPanel ClipToBounds="True" Orientation="Horizontal" IsItemsHost="True"/> 
      </Border> 
     </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
    </Style> 
    <Style x:Key="{x:Type MenuItem}" TargetType="{x:Type MenuItem}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
     <ControlTemplate TargetType="{x:Type MenuItem}"> 
      <Border x:Name="Border" 
        Background="{TemplateBinding Background}" 
        BorderBrush="{TemplateBinding BorderBrush}" 
        BorderThickness="1"> 
      <Grid> 
       <Grid.ColumnDefinitions> 
       <ColumnDefinition x:Name="Col0" MinWidth="17" Width="Auto" SharedSizeGroup="MenuItemIconColumnGroup"/> 
       <ColumnDefinition Width="Auto" SharedSizeGroup="MenuTextColumnGroup"/> 
       <ColumnDefinition Width="Auto" SharedSizeGroup="MenuItemIGTColumnGroup"/> 
       <ColumnDefinition x:Name="Col3" Width="14"/> 
       </Grid.ColumnDefinitions> 

       <!-- ContentPresenter to show an Icon if needed --> 
       <ContentPresenter Grid.Column="0" Margin="4,0,6,0" x:Name="Icon" VerticalAlignment="Center" ContentSource="Icon"/> 

       <!-- Glyph is a checkmark if needed for a checkable menu --> 
       <Grid Grid.Column="0" Visibility="Hidden" Margin="4,0,6,0" x:Name="GlyphPanel" VerticalAlignment="Center"> 
       <Path x:Name="GlyphPanelpath" VerticalAlignment="Center" Fill="{TemplateBinding Foreground}" Data="M0,2 L0,4.8 L2.5,7.4 L7.1,2.8 L7.1,0 L2.5,4.6 z" FlowDirection="LeftToRight"/> 
       </Grid> 

       <!-- Content for the menu text etc --> 
       <ContentPresenter Grid.Column="1" 
           Margin="{TemplateBinding Padding}" 
           x:Name="HeaderHost" 
           RecognizesAccessKey="True" 
           ContentSource="Header"/> 

       <!-- Content for the menu IGT --> 
       <ContentPresenter Grid.Column="2" 
           Margin="8,1,8,1" 
           x:Name="IGTHost" 
           ContentSource="InputGestureText" 
           VerticalAlignment="Center"/> 

       <!-- Arrow drawn path which points to the next level of the menu --> 
       <Grid Grid.Column="3" Margin="4,0,6,0" x:Name="ArrowPanel" VerticalAlignment="Center"> 
       <Path x:Name="ArrowPanelPath" HorizontalAlignment="Right" VerticalAlignment="Center" Fill="{TemplateBinding Foreground}" Data="M0,0 L0,8 L4,4 z"/> 
       </Grid> 

       <!-- The Popup is the body of the menu which expands down or across depending on the level of the item --> 
       <Popup IsOpen="{Binding Path=IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" x:Name="SubMenuPopup" Focusable="false" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}"> 
       <Border x:Name="SubMenuBorder" BorderBrush="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Menu}}}" BorderThickness="1" Padding="2,2,2,2"> 
        <Grid x:Name="SubMenu" Grid.IsSharedSizeScope="True"> 
        <!-- StackPanel holds children of the menu. This is set by IsItemsHost=True --> 
        <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/> 
        </Grid> 
       </Border> 
       </Popup> 
      </Grid> 
      </Border> 

      <!-- These triggers re-configure the four arrangements of MenuItem to show different levels of menu via Role --> 
      <ControlTemplate.Triggers> 
      <!-- Role = TopLevelHeader : this is the root menu item in a menu; the Popup expands down --> 
      <Trigger Property="Role" Value="TopLevelHeader"> 
       <Setter Property="Padding" Value="6,1,6,1"/> 
       <Setter Property="Placement" Value="Bottom" TargetName="SubMenuPopup"/> 
       <Setter Property="MinWidth" Value="0" TargetName="Col0"/> 
       <Setter Property="Width" Value="Auto" TargetName="Col3"/> 
       <Setter Property="Visibility" Value="Collapsed" TargetName="Icon"/> 
       <Setter Property="Visibility" Value="Collapsed" TargetName="GlyphPanel"/> 
       <Setter Property="Visibility" Value="Collapsed" TargetName="IGTHost"/> 
       <Setter Property="Visibility" Value="Collapsed" TargetName="ArrowPanel"/> 
      </Trigger> 

      <!-- Role = TopLevelItem : this is a child menu item from the top level without any child items--> 
      <Trigger Property="Role" Value="TopLevelItem"> 
       <Setter Property="Padding" Value="6,1,6,1"/> 
       <Setter Property="Visibility" Value="Collapsed" TargetName="ArrowPanel"/> 
      </Trigger> 

      <!-- Role = SubMenuHeader : this is a child menu item which does not have children --> 
      <Trigger Property="Role" Value="SubmenuHeader"> 
       <Setter Property="DockPanel.Dock" Value="Top"/> 
       <Setter Property="Padding" Value="0,2,0,2"/> 
      </Trigger> 

      <!-- Role = SubMenuItem : this is a child menu item which has children--> 
      <Trigger Property="Role" Value="SubmenuItem"> 
       <Setter Property="DockPanel.Dock" Value="Top"/> 
       <Setter Property="Padding" Value="0,2,0,2"/> 
       <Setter Property="Visibility" Value="Collapsed" TargetName="ArrowPanel"/> 
      </Trigger> 
      <Trigger Property="IsSuspendingPopupAnimation" Value="true"> 
       <Setter Property="PopupAnimation" Value="None" TargetName="SubMenuPopup"/> 
      </Trigger> 

      <!-- If no Icon is present the we collapse the Icon Content --> 
      <Trigger Property="Icon" Value="{x:Null}"> 
       <Setter Property="Visibility" Value="Collapsed" TargetName="Icon"/> 
      </Trigger> 

      <!-- The GlyphPanel contains the CheckMark --> 
      <Trigger Property="IsChecked" Value="true"> 
       <Setter Property="Visibility" Value="Visible" TargetName="GlyphPanel"/> 
       <Setter Property="Visibility" Value="Collapsed" TargetName="Icon"/> 
      </Trigger> 

      <!-- Using the system colors for the Menu Highlight and IsEnabled--> 
      <Trigger Property="IsHighlighted" Value="true"> 
       <Setter Property="Background" Value="{StaticResource HighlightedBackgroundBrush}" TargetName="Border"/> 
       <Setter Property="Foreground" Value="{StaticResource HighlightedText}"/> 
       <Setter Property="BorderBrush" Value="{StaticResource NormalBorderBrush}" TargetName="Border"/> 
      </Trigger> 
      <Trigger Property="IsHighlighted" Value="false"> 
       <Setter Property="Background" Value="{StaticResource MenuBackgroundBrush}" TargetName="Border"/> 
       <Setter Property="Foreground" Value="{StaticResource SolidMenuFontBrush}"/> 
       <Setter Property="BorderBrush" Value="{StaticResource MenuBackgroundBrush}" TargetName="Border"/> 
      </Trigger> 
      <Trigger Property="IsEnabled" Value="false"> 
       <Setter Property="Foreground" Value="LightGray"/> 
      </Trigger> 
      </ControlTemplate.Triggers> 
     </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
    </Style> 
    </Page.Resources> 
<Grid x:Name="mainGrid" 
     Background="#FF252525"> 

    <Menu x:Name="mainMenu" 
      Grid.ColumnSpan="2" 
      VerticalAlignment="Top"> 

     <MenuItem x:Name="fileMenu" 
        Header="File"> 

      <MenuItem x:Name="fileOpenMenuItem" 
         Header="Open..." /> 

      <MenuItem x:Name="fileSaveMenuItem" 
         Header="Save" /> 

      <MenuItem x:Name="fileSaveAsMenuItem" 
         Background="{DynamicResource menuItemBrush}" 
         Header="Save As..." /> 
     </MenuItem> 
    </Menu> 
    </Grid> 
</Page> 
+1

¿Hay alguna licencia de este tipo y los estilos que vienen con kaxaml? – NoOne

+1

@ NoOne, cada fragmento de código publicado en SE utiliza implícitamente la licencia de MIT. Kaxaml también utiliza MIT. –

0

Usted no puede hacerlo sin anular la plantilla para el opción del menú. En el fondo de la plantilla hay un control llamado "Part_Popup". Debes cambiar su color de fondo.

+0

¿Cómo accedería a esta propiedad? Sería bueno si pudiera anular esa propiedad. Intenté hacerlo a través del código C# usando algo como "this.FindResource (" Part_Popup) ", pero no puedo encontrar el recurso. – user62998

+0

Pruebe myMenu.Template.FindName (" Part_Popup ", this); – Micah

+0

Obtengo una InvaildOperationException: Esta operación solo es válida en elementos que tienen esta plantilla aplicada. Intenté reemplazar "esto" con el menú y eso tampoco funciona. – user62998

Cuestiones relacionadas