2

任何人都知道在 Win7 主题和 Win8 主题中看起来像常规按钮的 WPF 拆分按钮?我正在使用一个在 Win7 上看起来不错,但在 Win8 中却像拇指酸痛一样突出的一个:

奇怪的按钮

我已经在 codeplex 上尝试了 WPF Splitbutton 项目Banana SplitbuttonExtended WPF Toolkit 中的 splitbutton

有没有什么东西可以在 Win7 中提供 Win7 主题按钮和在 Win8 中提供 Win8 主题按钮?

我需要控件具有可绑定的 Command 属性并在按下向下箭头时显示上下文菜单。

4

3 回答 3

2

我采用了 Sten 的方法:将一个按钮嵌套在另一个按钮中。我使用用户控件使其可重用,将所有元素放在控件模板中,以便它可以将任意内容放入按钮中。

<UserControl 
  x:Class="VidCoder.Controls.SplitButton"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  mc:Ignorable="d"
  Loaded="SplitButton_OnLoaded">
  <UserControl.Template>
    <ControlTemplate TargetType="{x:Type UserControl}">
      <Button 
        HorizontalAlignment="Left" VerticalAlignment="Top" Name="mainButton" ContextMenuService.Placement="Bottom" 
        Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
        <Button.Content>
          <StackPanel Orientation="Horizontal" UseLayoutRounding="True">
            <ContentPresenter Margin="{TemplateBinding Padding}" />
            <Rectangle Width="1" Fill="#111111" Margin="0,2" />
            <Button Click="OnArrowClick">
              <Button.Template>
                <ControlTemplate TargetType="Button">
                  <Grid Background="Transparent" Name="buttonGrid">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                  </Grid>
                </ControlTemplate>
              </Button.Template>
              <Button.Content>
                <Path Data="M 0,0 L 8,0 L 4,4 Z" Fill="{TemplateBinding Foreground}" Margin="4 0 3 0" VerticalAlignment="Center"/>
              </Button.Content>
            </Button>
          </StackPanel>
        </Button.Content>
        <Button.ContextMenu>
          <ContextMenu Name="buttonMenu" ItemsSource="{Binding Path=MenuItemsSource, RelativeSource={RelativeSource TemplatedParent}}" />
        </Button.ContextMenu>
      </Button>
    </ControlTemplate>
  </UserControl.Template>
</UserControl>

代码隐藏公开了菜单项集合和 Command 属性:

public partial class SplitButton : UserControl
{
    private Button button;

    private ObservableCollection<object> menuItemsSource = new ObservableCollection<object>();

    public Collection<object> MenuItemsSource { get { return this.menuItemsSource; } }

    public SplitButton()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
        "Command",
        typeof (ICommand),
        typeof (SplitButton),
        new UIPropertyMetadata(null, OnCommandChanged));

    public ICommand Command
    {
        get
        {
            return (ICommand) GetValue(CommandProperty);
        }

        set
        {
            SetValue(CommandProperty, value);
        }
    }

    private static void OnCommandChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
    {
        if (eventArgs.NewValue != eventArgs.OldValue)
        {
            var splitButton = dependencyObject as SplitButton;

            if (splitButton.button != null)
            {
                splitButton.button.Command = eventArgs.NewValue as ICommand;
            }
        }
    }

    private void OnArrowClick(object sender, RoutedEventArgs e)
    {
        var buttonMenu = ContextMenuService.GetContextMenu(this.button);

        if (this.menuItemsSource.Count > 0 && buttonMenu != null)
        {
            buttonMenu.IsOpen = !buttonMenu.IsOpen;
            buttonMenu.PlacementTarget = this.button;
            buttonMenu.Placement = PlacementMode.Bottom;
        }
    }

    private void SplitButton_OnLoaded(object sender, RoutedEventArgs e)
    {
        this.button = this.Template.FindName("mainButton", this) as Button;
        if (this.Command != null)
        {
            this.button.Command = this.Command;
        }
    }
}

正在使用:

<controls:SplitButton HorizontalAlignment="Left" VerticalAlignment="Top" Command="{Binding TestCommand}">
    <controls:SplitButton.MenuItemsSource>
        <MenuItem Header="ham" Command="{Binding TestCommand2}" />
        <MenuItem Header="sandwiches" />
        <MenuItem Header="yum" />
    </controls:SplitButton.MenuItemsSource>
    <TextBlock Padding="4" Text="Testing" />
</controls:SplitButton>

拆分按钮使用示例

于 2012-12-16T20:56:01.827 回答
1

您总是可以用两个标准按钮制作自己的按钮,这并不难 - 只是按钮内的一个按钮,自定义内部按钮的样式以缺少边框,具有下拉三角形并具有“透明”背景(不是与导致点击的 {x:null} 背景相同)

大致是这样的:

<Button Style="outerStyle">
  <Button.Content>
     <StackPanel Orientation="Horizontal">
        <Label>Click Me</Label>
        <Button Style="{innerStyleWithTransparentBackground}"> ▼ </Button>
     </StackPanel>
  </Button.Content>
</Button>

如果您使用很多拆分按钮(无论如何都要这样做),您可以将此构造放在带有几个路由事件的用户控件中,否则您可以将其嵌套在其他代码中。

这不是最优雅的解决方案,但它可能是您能找到的最简单的解决方案之一。

于 2012-12-10T16:05:48.667 回答
0

“像大拇指一样伸出来”是 wpf 控件如何解决其样式的结果。默认情况下(也就是说,如果您没有通过 Style 属性提供 Style),splitbutton 将沿着资源树向上,直到找到 TargetType 为 splitButton 且隐式样式 x:Key 为 "{x:Type SplitButton} ”。如果它无法为您的拆分按钮找到样式,它将在主题文件中查找您当前使用的任何 Windows 主题。在 win7 中,这通常是 Aero.NormalColor.xaml。我不确定win8,但我想Metro.NormalColor.xaml(如果我错了,请纠正我)。如果在主题字典中找不到样式,它将在 Generic.xaml 中查找。无论如何,

示例:http: //msdn.microsoft.com/en-us/library/ms745683.aspx#styling_basics

于 2012-12-09T03:58:48.320 回答