[英]CustomControl with shapes
我想創建一個自定義控件以顯示餅圖。 我有一個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>
顯示內容是XAML中定義的控件默認外觀的部分。
我可能要做的就是獲取暴露DependencyProperty
的控件,該DependencyProperty
是代表切片的對象的集合。 每個對象將包含足夠的信息以正確顯示其對應的切片,而ItemsSource
更改時,控件的代碼將必須計算這些切片。
然后在XAML,結合,為一個ItemsControl
具有DataTemplate
結合所述切片描述對象實際PieSlice
對象,以及一個ItemsPanelTemplate
這可能只是一個Grid
或Canvas
,以允許多個節段堆積在彼此周圍。
您正在執行的操作是創建實際的PieSlice
對象,這沒關系,但是必須以不同的方式顯示它們-您可以將它們的集合綁定到使用ContentControl
作為其ItemTemplate
的ItemsControl
,並將Content
綁定到每個PieSlice
。
<DataTemplate><ContentControl Content="{Binding}" /></DataTemplate>
有關為WPF和Silverlight創建自定義控件的信息將在這里為您提供很好的服務,因為基本思想和許多技術在WinRT中都是相同的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.