WPF转换器隐含在自定义控件中?

时间:2017-06-26 22:05:14

标签: wpf binding custom-controls dependency-properties

在我绘制饼图的WPF自定义控件中,我成功地绘制了一个饼图,给出了字符串中的一组值,例如" 10 20 30"会绘制一个正确比例的饼图。我将DrawingImage的绘图属性绑定到转换器以将字符串转换为DrawingGroup。这很好用,但我试图绕过对转换器的需求。

这是我的MainWindow:

<Grid Margin="10">

    <local:PieChart DrawingCode="289 666 1337 780" Width="400" Height="400" RingWidth="300" Background="White" />

</Grid>

以下是我的自定义控件模板:

<Style TargetType="{x:Type local:PieChart}">
    <Setter Property="HorizontalContentAlignment" Value="Center" />
    <Setter Property="VerticalContentAlignment" Value="Center" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:PieChart}">
                <Grid>
                    <Image Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
                        <Image.Source>
                            <DrawingImage Drawing="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DrawingCode}" />
                        </Image.Source>
                    </Image>
                    <Ellipse Width="{TemplateBinding RingWidth}" Height="{TemplateBinding RingWidth}" Fill="{TemplateBinding Background}" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

最后,这是我对Custom Control类的尝试:

public class PieChart : Control
{
    public static readonly DependencyProperty DrawingCodeProperty = DependencyProperty.Register("DrawingCode", typeof(string), typeof(PieChart), new UIPropertyMetadata(null));
    public static readonly DependencyProperty RingWidthProperty = DependencyProperty.Register("RingWidth", typeof(double), typeof(PieChart), new UIPropertyMetadata(null));

    static PieChart()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(PieChart), new FrameworkPropertyMetadata(typeof(PieChart)));
    }

    public string DrawingCode
    {                                    
        get { return DrawingCodeConverter((string)GetValue(DrawingCodeProperty)); }
        set { SetValue(DrawingCodeProperty, value); }
    }

    public double RingWidth
    {
        get { return (double)GetValue(RingWidthProperty); }
        set { SetValue(RingWidthProperty, this.Width - value); }
    }

    public DrawingGroup DrawingCodeConverter(string value)
    {
        // This converter works but is long so I removed it from the post.
    }
}

我很确定问题出在我应该使用的数据类型的某个地方。另外,如果有一种完全不同的方式来做我不知道的事情,请告诉我。另请注意,RingWidth不是问题,它是DrawingCode。

1 个答案:

答案 0 :(得分:1)

在XAML中访问属性或通过Binding,Style Setter,Animation等访问属性时,可以绕过依赖项属性的CLR包装器的getter和setter.WPF然后直接调用GetValue和SetValue。原因在XAML Loading and Dependency Properties

中解释

因此,您必须在getter和setter中调用除GetValue和SetValue之外的任何其他内容。相反,使用PropertyChangedCallback声明您的依赖项属性,如下所示:

public static readonly DependencyProperty DrawingCodeProperty =
    DependencyProperty.Register(
        "DrawingCode",
        typeof(string),
        typeof(PieChart),
        new FrameworkPropertyMetadata(DrawingCodePropertyChanged));

public string DrawingCode
{
    get { return (string)GetValue(DrawingCodeProperty); }
    set { SetValue(DrawingCodeProperty, value); }
}

private static void DrawingCodePropertyChanged(
    DependencyObject o, DependencyPropertyChangedEventArgs e)
{
    var pieChart = (PieChart)o;
    pieChart.SetDrawingCode((string)e.NewValue);
}

private void SetDrawingCode(string drawingCode)
{
    var drawingGroup = DrawingCodeConverter(drawingCode);
    // do something with drawingGroup 
}