ワードの下線ボタン

ワードの下線ボタンって、スプリットボタンでもなく、トグルボタンでもなく、その両方ですよね。

そこで、wpfで、それを作ってみました。(名称は、SplitToggleButtonです。)

 

まずは、コードです。

 

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_ToggleButton", Type = typeof(ToggleButton))]
[TemplatePart(Name = "PART_DropDownButton", Type = typeof(ToggleButton))]
public class SplitToggleButton : Control
{
static SplitToggleButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(SplitToggleButton), new FrameworkPropertyMetadata(typeof(SplitToggleButton)));
}

public SplitToggleButton()
{
DefaultStyleKey = typeof(SplitToggleButton);
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(SplitToggleButton),
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(SplitToggleButton),
new PropertyMetadata(((Object)"")));


public object DropDownContent
{
get
{
return (object)GetValue(DropDownContentProperty);
}

set
{


SetValue(DropDownContentProperty, value);

 

}
}

public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.Register(
"IsChecked", typeof(bool), typeof(SplitToggleButton),
new PropertyMetadata(false, new PropertyChangedCallback(IsCheckedChangedCallback)));

public bool IsChecked
{
get
{
return (bool)GetValue(IsCheckedProperty);
}

set
{


SetValue(IsCheckedProperty, value);

 

}
}

private static void IsCheckedChangedCallback(DependencyObject obj,
DependencyPropertyChangedEventArgs args)
{
SplitToggleButton ctl = (SplitToggleButton)obj;
bool newValue = (bool)args.NewValue;

// Call UpdateStates because the Value might have caused the
// control to change ValueStates.
ctl.UpdateStates(true);

// Call OnValueChanged to raise the ValueChanged event.

if (newValue == true)
{
ctl.OnIsCheckedChanged(
new System.Windows.RoutedEventArgs(CheckedEvent));
}
else if(newValue == false)
{

ctl.OnIsCheckedChanged(
new System.Windows.RoutedEventArgs(UncheckedEvent));

}


ctl.ToggleButtonElement.IsChecked = newValue;


}

public static readonly RoutedEvent CheckedEvent =
EventManager.RegisterRoutedEvent("Checked", RoutingStrategy.Direct,
typeof(System.Windows.RoutedEventHandler), typeof(SplitToggleButton));

/// <summary>
/// チェックされたときに発生
/// </summary>
public event System.Windows.RoutedEventHandler CheckedChanged
{
add { AddHandler(CheckedEvent, value); }
remove { RemoveHandler(CheckedEvent, value); }
}

public static readonly RoutedEvent UncheckedEvent =
EventManager.RegisterRoutedEvent("Unchecked", RoutingStrategy.Direct,
typeof(System.Windows.RoutedEventHandler), typeof(SplitToggleButton));

/// <summary>
/// チェックされたときに発生
/// </summary>
public event System.Windows.RoutedEventHandler UncheckedChanged
{
add { AddHandler(UncheckedEvent, value); }
remove { RemoveHandler(UncheckedEvent, value); }
}


protected virtual void OnIsCheckedChanged(System.Windows.RoutedEventArgs e)
{
// Raise the ValueChanged event so applications can be alerted
// when Value changes.
RaiseEvent(e);
}


/// <summary>
/// ドロップ ダウンとして表示するコンテキスト メニューを取得または設定します。
/// </summary>

 

private void UpdateStates(bool useTransitions)
{


}

public override void OnApplyTemplate()
{
ToggleButtonElement = GetTemplateChild("PART_ToggleButton") as ToggleButton;
DropDownButtonElement = GetTemplateChild("PART_DropDownButton") as ToggleButton;
//TextElement = GetTemplateChild("TextBlock") as TextBlock;

UpdateStates(false);
}

private ToggleButton toggleButtonElement;

private ToggleButton ToggleButtonElement
{
get
{
return toggleButtonElement;
}

set
{
if (toggleButtonElement != null)
{
toggleButtonElement.Click -=
new RoutedEventHandler(toggleButtonElement_Click);

toggleButtonElement.Checked -= ToggleButtonElement_Checked;

toggleButtonElement.Unchecked -= ToggleButtonElement_Unchecked;
}
toggleButtonElement = value;

if (toggleButtonElement != null)
{
toggleButtonElement.Click +=
new RoutedEventHandler(toggleButtonElement_Click);

toggleButtonElement.Checked += ToggleButtonElement_Checked;

toggleButtonElement.Unchecked += ToggleButtonElement_Unchecked;
}
}
}

private void ToggleButtonElement_Unchecked(object sender, RoutedEventArgs e)
{
this.IsChecked = false;
}

private void ToggleButtonElement_Checked(object sender, RoutedEventArgs e)
{
this.IsChecked = true;
}

void toggleButtonElement_Click(object sender, RoutedEventArgs e)
{

}

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:SplitToggleButton}" TargetType="{x:Type local:SplitToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:SplitToggleButton">
<Grid Background="{TemplateBinding Background}">

 


<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>


<ToggleButton Name="PART_ToggleButton"
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>

 

 

}