为什么人们不将 DependencyProperties 包装在泛型类中?

发布于 2024-10-08 12:31:47 字数 1477 浏览 0 评论 0原文

我不喜欢 dp 的冗长,因为大多数代码只是重复,所以我只是将其包装在一个泛型类中。

看过相当多的示例代码后,我想知道为什么更多的人不这样做。

我在演示应用程序中没有遇到任何问题,这使得 ViewModel 更易于管理。

示例:

class GenericDependancyProperty<T> : DependencyObject
{
    // Value dependency property
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register( "Value", typeof( T ), typeof( GenericDependancyProperty ),
            new FrameworkPropertyMetadata( (T)default(T),
                new PropertyChangedCallback( OnValueChanged ) ) );

    // getter/setter for the Value dependancy property
    public T Value
    {
        get { return (T)GetValue( ValueProperty ); }
        set { SetValue( ValueProperty, value ); }
    }

    // Handles changes to the Value property.       
    private static void OnValueChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
    {
        GenericDependancyProperty<T> target = (GenericDependancyProperty<T>)d;
        T oldValue = (T)e.OldValue;
        T newValue = target.Value;
        target.OnValueChanged( oldValue, newValue );
    }

    // Provides derived classes an opportunity to handle changes to the Value property. 
    protected virtual void OnValueChanged( T oldValue, T newValue )
    {
        if ( ValueChanged != null )
        {
            ValueChanged( newValue );
        }
    }

    // Value changed event
    public event Action<T> ValueChanged;
}

这是一个坏主意吗?

I didn't like how verbose dp's are, since most of the code is just repeated, I just wrapped it in a generic class.

Having seen quite allot of sample code, I was wondering why more people aren't doing the same.

I haven't come across any problems to speak of in my demo application, and it makes the ViewModels easier to manage.

Sample:

class GenericDependancyProperty<T> : DependencyObject
{
    // Value dependency property
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register( "Value", typeof( T ), typeof( GenericDependancyProperty ),
            new FrameworkPropertyMetadata( (T)default(T),
                new PropertyChangedCallback( OnValueChanged ) ) );

    // getter/setter for the Value dependancy property
    public T Value
    {
        get { return (T)GetValue( ValueProperty ); }
        set { SetValue( ValueProperty, value ); }
    }

    // Handles changes to the Value property.       
    private static void OnValueChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
    {
        GenericDependancyProperty<T> target = (GenericDependancyProperty<T>)d;
        T oldValue = (T)e.OldValue;
        T newValue = target.Value;
        target.OnValueChanged( oldValue, newValue );
    }

    // Provides derived classes an opportunity to handle changes to the Value property. 
    protected virtual void OnValueChanged( T oldValue, T newValue )
    {
        if ( ValueChanged != null )
        {
            ValueChanged( newValue );
        }
    }

    // Value changed event
    public event Action<T> ValueChanged;
}

Is this a bad idea?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

鱼忆七猫命九 2024-10-15 12:31:47

这不是一个坏主意,也值得一试,但它不会起作用!

您实际上已经定义了一个名为“Value”的依赖属性。如果您只通过 CLR 包装器(即 Value 属性的获取/设置代码)访问它,那就没问题。然而,框架的大部分内容直接影响依赖属性。例如,样式设置器、动画将无法使用您的依赖属性。

我也和您一样对 DP 样板代码感到痛苦,这就是为什么我想出了一个声明性解决方案:

[DependencyPropertyDecl("Maximum", typeof(double), 0.0)]
[DependencyPropertyDecl("Minimum", typeof(double), 0.0)]
public partial class RangeControl : UserControl
{
    ...
}

实际的依赖属性是由 Visual Studio 中的 T4 模板生成的。

https://blog. scottlogic.com/2009/08/18/declarative-dependency-property-definition-with-t4-dte.html

It is not a bad idea, and well worth a try, but it will not work!

You have essentially defined a single dependency property named "Value". This will be OK if you only ever access it via your CLR wrapper (i.e. the get / set code for your Value property). However, much of the framework affects the dependency property directly. For example, style setters, animations will not be able to use your dependency property.

I too share your pain with the DP boilerplate code, which is why I came up with a declarative solution:

[DependencyPropertyDecl("Maximum", typeof(double), 0.0)]
[DependencyPropertyDecl("Minimum", typeof(double), 0.0)]
public partial class RangeControl : UserControl
{
    ...
}

The actual dependency properties are generated by a T4 template within Visual Studio.

https://blog.scottlogic.com/2009/08/18/declarative-dependency-property-definition-with-t4-dte.html

请你别敷衍 2024-10-15 12:31:47

我认为要指出的主要事情是,您这样做似乎是为了使视图模型类更加整洁,但实际上没有任何理由在视图模型中使用依赖属性。

正如 Colin 的回答所示,最常见的是在派生/用户控件中声明依赖属性。视图模型通常包含标准属性并实现 INotifyPropertyChanged。

此外,将依赖属性放入派生控件类本身而不是单独的泛型/静态类中是有意义的,因为您需要静态引用它:
MySlider.SpecialOpacityProperty。如果您在单个类中拥有这些内容,则不能有 2 个具有相同名称的属性(对于不同的控件),或者如果您使用泛型类,则无法在 XAML 中引用它。

I think the main thing to point out is that you seem to be doing this to keep your view-model classes neater, but there isn't really any reason to use dependency properties in view-models to begin with.

As Colin's answer demonstrates, it is most common to declare dependency properties in derived/user controls. The view-model typically contains standard properties and implements INotifyPropertyChanged.

Furthermore, it makes sense to put dependency properties in the derived control class itself instead of a separate generic/static class because you'll need to reference it statically:
MySlider.SpecialOpacityProperty. If you have these things in a single class, then you couldn't have 2 properties with the same name (for different controls), or if you use a generic class you can't reference it in XAML.

空心空情空意 2024-10-15 12:31:47

由于您的 ValueProperty 是静态的,因此无论您如何实例化类,该值都不会改变。我不明白这会如何运作。

Since your ValueProperty is static, the value won't change no matter how you instantiate your class. I don't see how this would work.

如此安好 2024-10-15 12:31:47

你的解决方案不可行、不灵活,而且根本不可扩展。

由于 C# 只允许单个基类,按照您的方法,每个类可以同时拥有一个 DP

这就是为什么它行不通的原因。

为了减轻痛苦,您应该使用 snippetscode Generation,如 Colin 提到的。

请记住,我们都有同样的痛苦。

Your solution is not feasible, flexible and not scalable at all.

Since C# only allows single base class, with your approach, every class can have one DP at once.

That is why it won't work.

What you should do to ease your pain is use snippets or code generation as Colin mentioned.

And remember, we all share the same pain.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文