【问题标题】:Make a large model observable使大型模型可观察
【发布时间】:2015-04-09 21:01:08
【问题描述】:

我正在进行我的第二个 WPF 项目并遇到了一个不舒服的情况。这是我的模型:

public class Layout
{
    public string Name { get; set; }
    public Motor Motor { get; set; }
}

public class Motor
{
    public string Property1 { get; set; }
    ...
    public string Property150 { get; set; }
}

这是我的 MainViewModel:

public class MainViewModel : ViewModelBase
{
    public Motor Motor {get; set;}
    ...
}

好的,我已将电机类的所有 150 个属性绑定到文本框:

<TextBox Text="{Binding Layout.Motor.Property1}"/>

问题 1)如果我想在用户更改其中一项时触发一个操作,我是否必须执行 150 次??

    private string property1 { get; set; }
    public string Property1
    {
        get { return property1; }
        set
        {
            property1 = value;
            RaisePropertyChanged(() => Property1);
        }
    }

问题 2) 我必须在 MainViewModel 中,在模型“Motor”中实现它还是需要一个“MotorViewModel”?任何这些都意味着大量的复制和粘贴以及完全无用的编码..

感谢您的任何帮助和反馈!

【问题讨论】:

  • 为什么要绑定 150 个属性到文本框?哪个用户会在视图中阅读/填充/编辑所有这些内容?
  • 哇,这读起来很完美......它是...... [魔法]!很遗憾,默认情况下不包括在内。感谢您的链接
  • 为什么你的模型有 150 个属性,而不是一个 List&lt;string&gt; 之类的?

标签: c# wpf


【解决方案1】:

首先,RaisePropertyChanged 真正用于UI,当代码 更改项目时通知它。当然,您也可以手动监听,但通常不会。

您通常也不使用自动属性作为支持字段,但这可能是由于您的 PropertyChanged 实现。

现在已经不碍事了:

是的,你需要实现它,或者类似的东西可以让PropertyChanged 被提升 150 次。 现在,有人想知道为什么你在一个对象上有 150 个属性,所以您可能需要先重新考虑该设计。但如果你真的需要它们,那么是的,复制粘贴在你的未来。考虑编写一个代码 sn-p 让它运行得更快。

要回答您的其他问题,您可以轻松地将其放入“模型”对象中,只要该对象可以用作 DTO。换句话说,它实际上并没有以某种方式与模型相关联(例如,具有模型功能),但可以在层之间浮动。你甚至可以将 INPC 放在数据合约上,这不会造成任何伤害。

要考虑的另一件事是,如果您只想在 motor 发生更改时通知 UI,而不是其各个属性,您可以只通知 Motor 属性,所有绑定都会更新。

【讨论】:

  • 不,他不必那样做。有许多不同的方法来处理这种情况。你可以使用PropertyDescriptors,框架的动态特性等。你可能是对的,这很臭。
  • @Will 所有这些实际上只是隐藏了相同的确切代码(动态代码除外)。当然,它更清洁,但它仍然非常相似。编辑表明有办法让它更干净
  • 完全不一样,就像你描述的 PITA 是什么,一遍又一遍地写这些 INPC 属性,一遍又一遍,一遍又一遍,一遍又一遍,一遍又一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍又一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍一遍地说明。
  • @Will 我不确定你是否真的得到了 150 次 ;)
【解决方案2】:

动态救援!

public class DynamicDictionary : DynamicObject, INotifyPropertyChanged
{
    private readonly Dictionary<string, object> dictionary;

    public DynamicDictionary(Dictionary<string, object> dictionary)
    {
        this.dictionary = dictionary;
    }

    public override bool TryGetMember(
        GetMemberBinder binder, out object result)
    {
        return dictionary.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(
        SetMemberBinder binder, object value)
    {
        dictionary[binder.Name] = value;
        // magic!
        OnPropertyChanged(binder.Name);
        return true;
    }

    #region INPC implementation
    // SNIP!  I ain't writing all that junk out
    #endregion
}

(这段代码大部分来自this answer

绑定识别实现 IDynamicMetaObjectProvider 的类型,就像 DynamicObject 一样,并且知道如何使用它们。试试看。

【讨论】:

  • 呃...动态。不过,与 150 个完整的属性定义相比,我想如果我正在编写它,我会认真考虑它。
猜你喜欢
  • 2018-06-28
  • 2011-01-07
  • 1970-01-01
  • 2015-03-13
  • 2014-12-24
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 2022-07-20
相关资源
最近更新 更多