覆盖WPF中的UserControl属性

时间:2012-10-31 17:56:02

标签: c# wpf user-controls

我是 WPF 的新手,所以我对如何做到这一点有点不知所措。我今天创建了一个非常简单的视觉UserControl,它由一个网格组成,显示一个圆圈,两条虚线穿过它。目的是显示给定半径尺寸的圆。我喜欢能够隐藏高度和宽度,并使用名为RadiusSize的自定义属性来设置控件的大小。

Code Behind定义RadiusSize依赖属性,如下:

public static readonly DependencyProperty RadiusSizeProperty =
    DependencyProperty.Register("RadiusSize", typeof(double), typeof(Radius));

public double RadiusSize
{
    get { return (double)GetValue(RadiusSizeProperty); }
    set 
    { 
        SetValue(RadiusSizeProperty, value);
        Height = value * 2;
        Width = value * 2;
        RaisePropertyChanged("RadiusSize");
    }
}

在为给定的Radius控件设置XAML并且遗憾地将RadiusSize传递给Auto时,高度或宽度属性没有明显变化。如果删除,则默认为{{1}}。我想做什么?

4 个答案:

答案 0 :(得分:2)

问题是您已将逻辑放入DependencyProperty周围的'clr包装器属性'的setter中。这在WPF中不起作用。您应该将代码放入DependencyProperty声明中的DependencyPropertyChangedCallback。看看This tutorial

除此之外,您可以使用椭圆在屏幕上绘制圆圈,而不必实现自己的圆圈。

您的RaisePropertyChanged方法有何功能?您不应该在基于DependencyObject的类中实现INotifyPropertyChanged。

答案 1 :(得分:2)

是的,有可能。不,你做得不对。

有点难以判断你是如何在圆上设置宽度/高度的,但是你的代码中明显的新手错误就是你在DependencyProperty的setter中做了一些事情。

DP Binding未通过您的媒体资源的getter / setter访问。绑定系统在幕后工作,因此如果您绑定到类上的DP,则getter /更新绑定时不会调用setter。

那么,有哪些替代方案?许多。您可以将PropertyMetadata实例添加到指定回调的属性声明中,并在该回调中更新其他属性...或者您可以完全避免它。我会选择第二个。

如果我打算创建一个带有椭圆和其他图形的UserControl,我只需在ViewBox中拍摄视觉效果并自动拉伸到UserControl的大小,并忘记整个半径的东西。

但是如果您仍然对半径感兴趣,可以使用IValueConverter来完成工作。

public class RadiusConverter : IValueConverter
{
    public object Convert(object value, /*snip*/)
    {
        // check null, type, and double.NaN here
        return (double)value * 2;
    }
    /* snip, on the round trip same as before but / 2 */
}

然后,在您的UserControl中定义Radius属性,并

<UserControl x:Class="Derp"
    Width="{Binding Radius, Converter={StaticResource RadiusConverter}, RelativeSource={RelativeSource Self} />
<!-- snip -->

答案 2 :(得分:0)

看起来很好,只是,当您设置控件的高度时,您可能没有修改内部圆的高度,请尝试设置圆的高度和您包含的网格。

答案 3 :(得分:0)

正如另一张海报指出的那样,您将无法使用属性系统设置高度和宽度。相反,如果您想要自动设置控件的高度和宽度,则需要为RadiusSizeProperty DependencyProperty定义回调。

当你设置RadiusSize:

时,这样的东西会为你设置高度和宽度
    Public Shared RadiusSizeProperty As DependencyProperty = DependencyProperty.Register("RadiusSize",
                                                             GetType(Double),
                                                             GetType(Radius),
                                                             New PropertyMetadata(0.5, Sub(s, e)

                                                                                           Dim p As DependencyPropertyChangedEventArgs = e
                                                                                           Dim o As DependencyObject = s
                                                                                           o.SetValue(HeightProperty, p.NewValue)
                                                                                           o.SetValue(WidthProperty, p.NewValue)
                                                                                       End Sub))