三角形ユーザーコントロール
WPF の基本図形には Rectangle や Ellipse があるのに、三角形 Triangle がありません。あるパートナーさんから三角形はUIによく使うので、WPFのプリミティブとして必要だと言われたので、ユーザーコントロールで作ってみました。
Rectangle には Fill, Stroke, StrokeThickness 依存プロパティがあるので、同じように定義します。さらに依存プロパティとして VertexOffset を追加しました。これは正三角形でデフォルト形状を定義すると、直角三角形のような図形に変形できないので、いちばん上の頂点を左右にオフセットさせるパラメータです。デフォルトは50で、0が左の直角三角形、100が右の直角三角形になります(マイナスや100以上も可)。
XAMLでは直角三角形を PathGeometry を使って定義します。前述の4つの依存プロパティはバインディングを使って定義します。VertexOffset の型は double ですが、必要なのは Point なので、ConvertToPointコンバーターをコードビハインドで定義して使いました。
<UserControl x:Class="TriangleUserControl.Triangle"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TriangleUserControl"
x:Name="myTriangle" Background="Transparent" >
<UserControl.Resources>
<local:DoubleToPoint x:Key="ConvertToPoint"/>
</UserControl.Resources>
<Grid Margin="0">
<Path Stretch="Fill"
Fill="{Binding ElementName=myTriangle, Path=Fill}"
Stroke="{Binding ElementName=myTriangle, Path=Stroke}"
StrokeThickness="{Binding ElementName=myTriangle,
Path=StrokeThickness}" >
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="50,86.6" IsClosed="True">
<LineSegment Point="50, 86.6" />
<LineSegment Point="100, 86.6" />
<LineSegment
Point="{Binding ElementName=myTriangle,
Path=VertexOffset,
Converter={StaticResource ConvertToPoint}}" />
<LineSegment Point="0,86.6" />
<LineSegment Point="50,86.6" />
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
</Grid>
</UserControl>
コードビハインドでは依存プロパティと、コンバーターを定義するだけです。依存プロパティは、Visual Studio 2008 のコードエディタで「propdp」と入力すると、コードスニペットを作ってくれますから、型とデフォルト値を設定するだけで済むので簡単です。
#region Fill
public Brush Fill
{
get { return (Brush)GetValue(FillProperty); }
set { SetValue(FillProperty, value); }
}
public static DependencyProperty
FillProperty =
DependencyProperty.Register("Fill",
typeof(Brush),
typeof(Triangle),
new FrameworkPropertyMetadata(Brushes.White));
#endregion Fill
…
[ValueConversion(typeof(Double), typeof(Point))]
public class DoubleToPoint : IValueConverter
{
public object Convert(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
Double d = (Double)value;
return new Point(d,0.0);
}
public object ConvertBack(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
Point p = (Point)value;
return p.X;
}
}
このユーザーコントロールを使うときは、名前空間のプレフィックスは必要ですが、通常のRectangleなどと同じように使えます。
<tri:Triangle Width="100" Height="50"
Fill="Green"
Stroke="Red"
StrokeThickness="5"
VertexOffset="20" />
ちゃんとVS Designer や Expression Blendでも利用・編集できます。
プロジェクトを添付します。