円グラフを表示するカスタム コントロールを作成したいと思います。PieSlice クラス (WinRT ツールキット プロジェクトから取得) があります。
public class PieSlice : Path
{
#region StartAngle
public static readonly DependencyProperty StartAngleProperty =
DependencyProperty.Register(
"StartAngle",
typeof(double),
typeof(PieSlice),
new PropertyMetadata(
0d,
new PropertyChangedCallback(OnStartAngleChanged)));
public double StartAngle
{
get { return (double)GetValue(StartAngleProperty); }
set { SetValue(StartAngleProperty, value); }
}
private static void OnStartAngleChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var target = (PieSlice)sender;
var oldStartAngle = (double)e.OldValue;
var newStartAngle = (double)e.NewValue;
target.OnStartAngleChanged(oldStartAngle, newStartAngle);
}
private void OnStartAngleChanged(double oldStartAngle, double newStartAngle)
{
UpdatePath();
}
#endregion
#region EndAngle
public static readonly DependencyProperty EndAngleProperty =
DependencyProperty.Register(
"EndAngle",
typeof(double),
typeof(PieSlice),
new PropertyMetadata(
0d,
new PropertyChangedCallback(OnEndAngleChanged)));
public double EndAngle
{
get { return (double)GetValue(EndAngleProperty); }
set { SetValue(EndAngleProperty, value); }
}
private static void OnEndAngleChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var target = (PieSlice)sender;
var oldEndAngle = (double)e.OldValue;
var newEndAngle = (double)e.NewValue;
target.OnEndAngleChanged(oldEndAngle, newEndAngle);
}
private void OnEndAngleChanged(double oldEndAngle, double newEndAngle)
{
UpdatePath();
}
#endregion
#region Radius
public static readonly DependencyProperty RadiusProperty =
DependencyProperty.Register(
"Radius",
typeof(double),
typeof(PieSlice),
new PropertyMetadata(
0d,
new PropertyChangedCallback(OnRadiusChanged)));
public double Radius
{
get { return (double)GetValue(RadiusProperty); }
set { SetValue(RadiusProperty, value); }
}
private static void OnRadiusChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var target = (PieSlice)sender;
var oldRadius = (double)e.OldValue;
var newRadius = (double)e.NewValue;
target.OnRadiusChanged(oldRadius, newRadius);
}
private void OnRadiusChanged(double oldRadius, double newRadius)
{
this.Width = this.Height = 2 * Radius;
UpdatePath();
}
#endregion
private void UpdatePath()
{
var pathGeometry = new PathGeometry();
var pathFigure = new PathFigure();
pathFigure.StartPoint = new Point(Radius, Radius);
pathFigure.IsClosed = true;
// Starting Point
var lineSegment =
new LineSegment
{
Point = new Point(
Radius + Math.Sin(StartAngle * Math.PI / 180) * Radius,
Radius - Math.Cos(StartAngle * Math.PI / 180) * Radius)
};
// Arc
var arcSegment = new ArcSegment();
arcSegment.IsLargeArc = (EndAngle - StartAngle) >= 180.0;
arcSegment.Point =
new Point(
Radius + Math.Sin(EndAngle * Math.PI / 180) * Radius,
Radius - Math.Cos(EndAngle * Math.PI / 180) * Radius);
arcSegment.Size = new Size(Radius, Radius);
arcSegment.SweepDirection = SweepDirection.Clockwise;
pathFigure.Segments.Add(lineSegment);
pathFigure.Segments.Add(arcSegment);
pathGeometry.Figures.Add(pathFigure);
this.Data = pathGeometry;
this.InvalidateArrange();
}
}
そして今、複数のパイスライスを含むことができるコントロールを作成しようとしています
public class Pie : Control
{
#region Items Source
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register(
"ItemsSource",
typeof(IEnumerable),
typeof(Pie),
new PropertyMetadata(
null,
new PropertyChangedCallback(OnItemsSourceChanged)));
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
private static void OnItemsSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var target = (Pie)sender;
var oldItemsSource = (IEnumerable)e.OldValue;
var newItemsSource = (IEnumerable)e.NewValue;
target.OnItemsSourceChanged(oldItemsSource, newItemsSource);
}
private void OnItemsSourceChanged(IEnumerable oldItemsSource, IEnumerable newItemsSource)
{
UpdatePieSlices();
}
#endregion
public Pie()
{
this.DefaultStyleKey = typeof(Pie);
}
private void UpdatePieSlices()
{
double startAngle = 0;
foreach (KeyValuePair<string, double> item in ItemsSource)
{
PieSlice slice = new PieSlice()
{
Fill = new SolidColorBrush(Colors.Red),
Radius = 100, StartAngle = startAngle,
EndAngle = (item.Value / 100.0) * 360
};
startAngle = (item.Value / 100.0) * 360;
}
}
}
ItemsSource はKeyValuePair<string, int>
、スライスの名前とパーセンテージを表すコレクションです。スライスを表示したいのですが、方法がわかりません...
編集 :
私はこれを試しましたが、うまくいきません
<Style TargetType="control:Pie">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="control:Pie">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ItemsControl
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
ItemsSource="{Binding Path=ItemsSource}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid></Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>