0

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

后面的代码定义了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. 我想做的事可能吗?

4

4 回答 4

2

问题是您已将逻辑放入 DependencyProperty 周围的“clr 包装器属性”的设置器中。这在 WPF 中不起作用。您应该将您的代码放入 DependencyProperty 声明中的 DependencyPropertyChangedCallback。看看这个教程

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

你的 RaisePropertyChanged 方法是做什么的?您不应在基于 DependencyObject 的类中实现 INotifyPropertyChanged。

于 2012-10-31T18:07:41.840 回答
2

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

很难说出您是如何在圆上设置宽度/高度的,但是您在代码中遇到的明显新手错误是您在 DependencyProperty 的设置器中做事。

DP不能通过您的属性的 getter/setter 访问Binding。 绑定系统在幕后工作,因此如果您绑定到类上的 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 */
}

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

<UserControl x:Class="Derp"
    Width="{Binding Radius, Converter={StaticResource RadiusConverter}, RelativeSource={RelativeSource Self} />
<!-- snip -->
于 2012-10-31T18:07:44.507 回答
0

看起来不错,只是,当您设置控件的高度时,您可能不会修改内部圆圈的高度,请尝试设置您还包含的圆圈和网格的高度。

于 2012-10-31T18:06:21.967 回答
0

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

当你设置 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))
于 2012-10-31T18:07:56.660 回答