SplitButton - wpfコントロール
wpfのスプリットボタンを作ってみました。
まずは、コードです。
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Controls.Primitives;
namespace OkaSharp{
[TemplatePart(Name = "PART_ActionButton", Type = typeof(Button))]
[TemplatePart(Name = "PART_DropDownButton", Type = typeof(ToggleButton))]
public class SplitButton : Control
{
static SplitButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(SplitButton), new FrameworkPropertyMetadata(typeof(SplitButton)));
}
public SplitButton()
{
DefaultStyleKey = typeof(SplitButton);
this.IsTabStop = true;
var binding = new Binding("DropDownContextMenu.IsOpen") { Source = DropDownButtonElement };
this.SetBinding(ToggleButton.IsCheckedProperty, binding);
}
public static readonly DependencyProperty ContentProperty =
DependencyProperty.Register(
"Content", typeof(object), typeof(SplitButton),
new PropertyMetadata(((Object)"")));
public object Content
{
get
{
return (object)GetValue(ContentProperty);
}
set
{
SetValue(ContentProperty, value);
}
}
public static readonly DependencyProperty DropDownContentProperty =
DependencyProperty.Register(
"DropDownContent", typeof(object), typeof(SplitButton),
new PropertyMetadata(((Object)"")));
public object DropDownContent
{
get
{
return (object)GetValue(DropDownContentProperty);
}
set
{
SetValue(DropDownContentProperty, value);
}
}
public static readonly RoutedEvent ActionClickEvent =
EventManager.RegisterRoutedEvent("ActionClick", RoutingStrategy.Direct,
typeof(System.Windows.RoutedEventHandler), typeof(DropDownMenuButton));
public event System.Windows.RoutedEventHandler ActionClick
{
add { AddHandler(ActionClickEvent, value); }
remove { RemoveHandler(ActionClickEvent, value); }
}
/// <summary>
/// ドロップ ダウンとして表示するコンテキスト メニューを取得または設定します。
/// </summary>
private void UpdateStates(bool useTransitions)
{
}
public override void OnApplyTemplate()
{
ActionButtonElement = GetTemplateChild("PART_ActionButton") as Button;
DropDownButtonElement = GetTemplateChild("PART_DropDownButton") as ToggleButton;
//TextElement = GetTemplateChild("TextBlock") as TextBlock;
UpdateStates(false);
}
private Button actionButtonElement;
private Button ActionButtonElement
{
get
{
return actionButtonElement;
}
set
{
if (actionButtonElement != null)
{
actionButtonElement.Click -=
new RoutedEventHandler(actionButtonElement_Click);
}
actionButtonElement = value;
if (actionButtonElement != null)
{
actionButtonElement.Click +=
new RoutedEventHandler(actionButtonElement_Click);
}
}
}
void actionButtonElement_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(ActionClickEvent, this));
}
private ToggleButton dropDownButtonElement;
private ToggleButton DropDownButtonElement
{
get
{
return dropDownButtonElement;
}
set
{
if (dropDownButtonElement != null)
{
dropDownButtonElement.Click -=
new RoutedEventHandler(dropDownButtonElement_Click);
}
dropDownButtonElement = value;
if (dropDownButtonElement != null)
{
dropDownButtonElement.Click +=
new RoutedEventHandler(dropDownButtonElement_Click);
}
}
}
void dropDownButtonElement_Click(object sender, RoutedEventArgs e)
{
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
Focus();
}
protected override void OnGotFocus(RoutedEventArgs e)
{
base.OnGotFocus(e);
UpdateStates(true);
}
protected override void OnLostFocus(RoutedEventArgs e)
{
base.OnLostFocus(e);
UpdateStates(true);
}
}
}
次に、スタイルです。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:OkaSharp"
>
<Style x:Key="{x:Type local:SplitButton}" TargetType="{x:Type local:SplitButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:SplitButton">
<Grid Background="{TemplateBinding Background}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Name="PART_ActionButton"
Grid.Row="0"
Grid.Column="0"
Content="{TemplateBinding Content}" />
<ToggleButton Name="PART_DropDownButton"
Grid.Row="0"
Grid.Column="1"
Content="▼" />
</Grid>
<Popup AllowsTransparency="True"
Focusable="False"
HorizontalOffset="1"
IsOpen="{Binding Path=IsChecked,
ElementName=PART_DropDownButton}"
Placement="Bottom"
StaysOpen="False"
VerticalOffset="1">
<Border Background="White" BorderBrush="Gray">
<ContentPresenter Content="{TemplateBinding DropDownContent}" />
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>