Jaa


三角形ユーザーコントロール

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" />

 

 

 

image

ちゃんとVS Designer や Expression Blendでも利用・編集できます。

 

 

 

 image

プロジェクトを添付します。

SimpleTriangle.zip