0

円グラフを表示するカスタム コントロールを作成したいと思います。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>
4

1 に答える 1

1

表示は、XAML で定義された、コントロールの既定の外観の領域です。

私がおそらく行うことはDependencyProperty、スライスを表すオブジェクトのコレクションである を公開するコントロールを取得することです。各オブジェクトには、対応するスライスを正しく表示するのに十分な情報が含まれており、ItemsSource変更時にコントロールのコードで計算する必要があります。

次に、XAML で、それを、スライス記述オブジェクトを実際のオブジェクトにバインドするItemsControlを持つにバインドします。DataTemplatePieSliceItemsPanelTemplateGridCanvas

あなたがしているのは、実際のPieSliceオブジェクトを作成することです。これは問題ありませんが、別の方法で表示する必要があります。それらのコレクションをとしてItemsControl使用するにバインドし、それぞれにバインドすることができます。ContentControlItemTemplateContentPieSlice

<DataTemplate><ContentControl Content="{Binding}" /></DataTemplate>

WPF と Silverlight のカスタム コントロールの作成に関する情報は、ここで役に立ちます。基本的な考え方とテクノロジの多くは WinRT でも同じだからです。

于 2012-06-18T14:59:48.967 に答える