2012-06-18 2 views
0

파이 차트를 표시하기 위해 사용자 지정 컨트롤을 만들고 싶습니다. 내가 할 수있는 여러 개의 원형 조각셰이프가있는 CustomControl

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가 인을 포함하는 컨트롤을 만드는 노력하고

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(); 
    } 
} 

그리고 지금 : 나는 (내가 WinRT 툴킷 프로젝트에서 가져온)를 PieSlice 클래스가 슬라이스의 이름과 백분율을 나타내는 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> 

답변

1

디스플레이를 작동하지 않는 지방이다

편집이 ... 나는 조각을 표시하고 싶습니다하지만 난 아무 생각이 어떻게 XAML에 정의 된 컨트롤의 기본 모양

내가 할 수있는 것은 슬라이스를 나타내는 개체 컬렉션 인 DependencyProperty을 노출하는 컨트롤을 얻는 것입니다. 각 객체는 해당 슬라이스를 올바르게 표시 할 수있는 충분한 정보를 포함합니다.이 슬라이스는 ItemsSource이 변경 될 때 컨트롤의 코드에서 계산해야합니다.

그런 다음 XAML에서 단지 Grid 또는 Canvas는 세그먼트마다 주위 쌓일 수 있도록 실제 PieSlice 오브젝트 슬라이스 설명 객체를 결합하는 DataTemplate을 갖는 ItemsControl, 아마 인 ItemsPanelTemplate 해당 바인딩 다른.

당신이 괜찮 실제 PieSlice 개체를 만드는 일을하고 있지만 그들은 다르게 표시 할 필요가 - 당신은 ItemTemplateContentControl를 사용하는 ItemsControl에의 컬렉션을 결합 수, 각 PieSliceContent 바인딩 . 기본 아이디어로, 여기에서도 서비스를 제공합니다 WPF와 실버 라이트에 대한 사용자 정의 컨트롤을 생성하고 많은 기술에 대한

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

정보는 WinRT에서 동일합니다.

+0

자세한 내용을 제공해 주시겠습니까? xaml로 내 게시물을 편집했지만 여전히 작동하지 않습니다. – Peekyou

+0

이제 작동합니다! 고맙습니다. – Peekyou

+0

@Peekyou 최종 해결 솔루션으로 질문을 편집 해주십시오. 감사. –

관련 문제