我想创建一个自定义控件以显示饼图。 我有一个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>
答案 0 :(得分:1)
显示是控件默认外观的省份,在XAML中定义。
我可能做的是让控件公开DependencyProperty
,它是表示切片的对象的集合。每个对象都包含足够的信息来正确显示它对应的切片,当ItemsSource
更改时,控件的代码必须计算这些切片。
然后在XAML中,将其绑定到ItemsControl
,其DataTemplate
将切片描述对象绑定到实际的PieSlice
对象,并ItemsPanelTemplate
可能是Grid
只需Canvas
或PieSlice
即可让细分受众群相互堆积。
你正在做的是创建实际的ItemsControl
对象,这是好的,但它们必须以不同的方式显示 - 你可以将它们的集合绑定到使用{{1}的ContentControl
} ItemTemplate
,将Content
绑定到每个PieSlice
。
<DataTemplate><ContentControl Content="{Binding}" /></DataTemplate>
有关为WPF和Silverlight创建自定义控件的信息在这里很有用,因为WinRT中的基本思想和大部分技术都是相同的。