MVVM 模型应该是什么样的?

发布于 2024-11-07 11:40:29 字数 266 浏览 0 评论 0 原文

您好,我有 3 个关于 MVVM 模型的问题。

  1. 有没有办法绕过冗余的 PropertyChanged("PropName");
  2. 将 POCO 对象包装到 WPF 的最佳方法是什么 INotifyPropertyChanged, IDataErrorInfo
  3. 我应该如何与(WPfWrapers - POCO)在 ViewModel 内 - 通过强制转换或属性...

谢谢。

Hello i have 3 questions about MVVM Model.

  1. Isn't there any way to bypass that redundant PropertyChanged("PropName");
  2. What is the best way to wrap POCO objects to WPF INotifyPropertyChanged, IDataErrorInfo
  3. How should i interact with (WPfWrapers - POCO) inside ViewModel - via casting, or property...

Thanks.

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

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

发布评论

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

评论(5

心清如水 2024-11-14 11:40:29

这里有 3 个答案:

  1. 您可以找到引发 PropertyChanged 事件的替代方案,而无需在 .NET 社区。然而,它们都有其他缺点(例如性能)。

  2. 最好的方法是直接在模型中实现 INotifyPropertyChanged 和 IDataErrorInfo。这并不总是可能的。如果您需要包装模型类,那么您可能会查看 DataModel 概念。

  3. 我不确定我是否理解了最后一个问题,但这是一个答案。 ViewModel 或 DataModel 应直接与模型交互。但这些类不应该以直接的方式与视图交互。对于此类场景,请使用接口(例如 IView)。

更多信息可在此处找到:WPF 应用程序框架 (WAF)

Here are 3 answers:

  1. You find alternatives of raising the PropertyChanged event without passing the “PropName” as string parameter in the .NET community. However, all of them have other drawbacks (e.g. performance).

  2. The best way is to implement INotifyPropertyChanged and IDataErrorInfo directly in the Model. That’s not always possible. If you need to wrap you Model classes then you might have a look at the DataModel concept.

  3. I’m not sure if I understand the last question right but here is an answer. The ViewModel or DataModel should interact with the Model directly. But these classes shouldn’t interact with the View in a direct way. Use interfaces (e.g. IView) for such scenarios.

More information can be found here: WPF Application Framework (WAF)

[浮城] 2024-11-14 11:40:29
  1. 是的,您可以使用 Lamdba 表达式来完成此操作。但这会花费一些处理器时间(进行一些快速测量:这种方法比使用字符串常量慢大约 200 倍。在频繁使用的 POCO 上使用表达式时请记住这一点):

    私有字符串 ExtractPropertyName( Expression> propertyExpresssion )
    {
        if ( 属性表达式 == null )
        {
            抛出新的ArgumentNullException(“propertyExpression”);
        }
    
        var memberExpression = propertyExpression.Body as MemberExpression;
        if ( 成员表达式 == null )
        {
            throw new ArgumentException( "该表达式不是成员访问表达式。", "propertyExpression" );
        }
    
        var property = memberExpression.Member as PropertyInfo;
        if ( 属性 == null )
        {
            throw new ArgumentException( "成员访问表达式未访问属性。", "propertyExpression" );
        }
    
        if ( !property.DeclaringType.IsAssignableFrom( this.GetType( ) ) )
        {
            throw new ArgumentException( "引用的属性属于不同类型。", "propertyExpression" );
        }
    
        var getMethod = property.GetGetMethod( true );
        if ( getMethod == null )
        {
            // 这不应该发生 - 表达式会在到达这么远之前拒绝该属性
            throw new ArgumentException( "引用的属性没有 get 方法。", "propertyExpresssion" );
        }
    
        if ( getMethod.IsStatic )
        {
            throw new ArgumentException( "引用的属性是静态属性。", "propertyExpression" );
        }
    
        返回memberExpression.Member.Name;
    }
    
    私有字符串 myProperty;
    公共字符串我的财产
    {
        得到
        {
            归还我的财产;
        }
        放
        {
            我的属性=值;
            this.RaisePropertyChanged( ( ) => MyProperty );
        }
    }
    
    protected void RaisePropertyChanged( Expression> propertyExpression )
    {
        var 属性名称 = ExtractPropertyName( 属性表达式 );
        this.RaisePropertyChanged( propertyName );
    }
    
  2. 我认为您不这样做必须包装它们(除了创建相应的视图模型之外)。 POCO 用作模型,接口由视图模型实现。

  3. 当您不包装 POCO 时,这个问题就已经过时了。
  1. Yes, you can do this with a Lamdba expression. But this will cost some processor time (made some quick measurements: this approach is around 200 times slower than using the the string constant. Keep this in mind when using the expression on highly frequented POCOs):

    private string ExtractPropertyName<T>( Expression<Func<T>> propertyExpresssion )
    {
        if ( propertyExpresssion == null )
        {
            throw new ArgumentNullException( "propertyExpresssion" );
        }
    
        var memberExpression = propertyExpresssion.Body as MemberExpression;
        if ( memberExpression == null )
        {
            throw new ArgumentException( "The expression is not a member access expression.", "propertyExpresssion" );
        }
    
        var property = memberExpression.Member as PropertyInfo;
        if ( property == null )
        {
            throw new ArgumentException( "The member access expression does not access a property.", "propertyExpresssion" );
        }
    
        if ( !property.DeclaringType.IsAssignableFrom( this.GetType( ) ) )
        {
            throw new ArgumentException( "The referenced property belongs to a different type.", "propertyExpresssion" );
        }
    
        var getMethod = property.GetGetMethod( true );
        if ( getMethod == null )
        {
            // this shouldn't happen - the expression would reject the property before reaching this far
            throw new ArgumentException( "The referenced property does not have a get method.", "propertyExpresssion" );
        }
    
        if ( getMethod.IsStatic )
        {
            throw new ArgumentException( "The referenced property is a static property.", "propertyExpresssion" );
        }
    
        return memberExpression.Member.Name;
    }
    
    private string myProperty;
    public string MyProperty
    {
        get
        {
            return myProperty;
        }
        set
        {
            myProperty = value;
            this.RaisePropertyChanged( ( ) => MyProperty );
        }
    }
    
    protected void RaisePropertyChanged<T>( Expression<Func<T>> propertyExpression )
    {
        var propertyName = ExtractPropertyName( propertyExpression );
        this.RaisePropertyChanged( propertyName );
    }
    
  2. I think you don't have to wrap them (besides creating a coresponding view model). The POCOs are used as model and the interfaces are implemented by the viewmodel.

  3. This question is obsolete when you don't wrap the POCOs.
携余温的黄昏 2024-11-14 11:40:29

关于你的第一个问题:
看看这篇文章

并且< a href="http://www.google.nl/search?q=INotifyPropertyChanged%20implementations" rel="nofollow">进行 google 搜索

有很多方法(和讨论)

我的2分钱:

首先
还有第二个

On your first question:
Have a look at this post

And do a google search

There are many ways (and discussions)

My 2 cents:

First
And second

原野 2024-11-14 11:40:29

还可以选择在视图模型中使用依赖项属性。很多人似乎不喜欢这样做,因为它们是 wpf 的一部分并且具有线程关联性(您只能从创建该特定对象的线程中调用依赖属性方法,

我个人从未发现这是一个问题,因为您' re view 既依赖于 wpf 并且具有线程亲和性,因此即使使用 INotifyPropertyChanged,您仍然必须从正确的线程触发 PropertyChanged 事件

Dependecy 属性已内置通知支持,并且不需要。 wpf 进行任何反射,因此它们的数据绑定速度更快(但设置/获取速度较慢,尽管时间范围很短)

您的场景可能与我的不同,但我认为它值得一看:)

There is also the option to use Dependency properties in your viewmodel. Alot of people doesnt seem to like doing this because they are a part of wpf and have thread affinity (you can only call the dependency property method from the thread that created that perticular object

I personaly have never found this to be a problem since you're view is both dependent on wpf and has thread affinity anyway, so you even if INotifyPropertyChanged is used you still have to fire the PropertyChanged event from the correct thread.

Dependecy properties have built in notification support and does not require wpf to do any reflection, so they are faster for data binding (but slower to set/get albeit on a small time scale)

your scenario might be diffrent than mine, but its someting to look at i think :)

旧人 2024-11-14 11:40:29

您可以使用 .NET 4.5 名为“CallerMemberName”的新功能来避免对属性名称进行硬编码。

You can use the new feature of .NET 4.5 named "CallerMemberName" to avoid hard-coding the property name.

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