【问题标题】:XDocument to live updated viewmodelXDocument 实时更新视图模型
【发布时间】:2013-01-23 22:05:07
【问题描述】:

有没有人知道让视图模型与不断变化的 XDocument 保持同步的简单方法? XDocument 来自 Microsoft.VisualStudio.XmlEditor.XmlModel 类 (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.xmleditor.xmlmodel.aspx)。当用户在 Visual Studio 编辑器中更改文本时,相同的 XDocument 会不断更新。

我不想每次都使用序列化将整个 xml 解析为对象。文档非常好,那会是很大的性能瓶颈。

这个问题和我的问题有点相似,但是“(helper)”要填什么? ViewModel on top of XDocument

要求: - 当 XDocument 树中的某些内容发生更改时,必须更新视图模型,并且必须应用最小的更改。 - 对象的子对象更改时的事件。 - 有多个相同子标签时的 Observablecollections - 必须重用对象,每次从我的自定义类访问对象时都没有新元素。所以必须使用属性来保存从 xml 生成的对象。必须使用新的子对象更新对象。

是否有框架或其他东西可以轻松完成这项任务?我想很多人已经做过这样的事情了,我不想重新发明轮子。

我希望这个问题有点清楚。

【问题讨论】:

  • 对于初学者来说,每个XObject 都有一个Changed 和一个Changing 事件。如果您能以某种方式为您感兴趣的每个子元素订阅这些事件,您就可以轻松地使用这些事件和观察者模式来更新您的 UI。
  • 你有我的例子吗?
  • 好的,谢谢。但我仍然认为必须有一些东西可以自动为我做这件事。保持 IEnumerable 与 ObservableCollection 同步,并且只为新的 XElements 创建该类的新实例,对于这些事件并不容易。 ObservableCollection 中的顺序也必须与 XDocument 中的相同。

标签: c# xml-parsing linq-to-xml viewmodel visual-studio-sdk


【解决方案1】:

您可以围绕 XElement 编写 ViewModel。

例如,

public class Model {

   protected XElement Element {
     get; set;
   }

   public Model() : this(null) { }

   public Model(XElement element) {
     // do some validation (XName)element.Name
     this.Element = element ?? new XElement("Model");
   }

   public string Name {
     get {
       return (string)Element.Attribute("Name");
     }
     set {
       // null: attribute is removed
       Element.SetAttributeValue(value);
     }
   }
}

你的 XML:

<Model Name="Marilyn" />

使用您的 XDocument,您可以阅读您的元素:

source.Select(xElement => new Model(xElement));

ObservableCollection 本身通过 INotifyPropertyChanged 模式获得通知:

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)
{
    var handler = PropertyChanged;
    if (handler != null)
        handler(this, new PropertyChangedEventArgs(propertyName));
}

在您的模型中,您会收到您在构造函数中分配的 XObject.Change 和 .Changed 事件的通知:

public Model() : this(null) {
  // call public Model(XElement element = null)
}

public Model(XElement element) {
  // do some validation (XName)element.Name
  this.Element = element ?? new XElement("Model");
  //this.Element.Changing += Element_Changing;
  this.Element.Changed += Element_Changed;
}

现在您可以将 XElement 更改连接到 INotifyProperty 更改:

protected void Element_Changed(object sender, XObjectChangeEventArgs ea) {
  var attribute = sender as XAttribute;
  if (attribute != null && attribute.Parent == this.Element) {
    // only attributes of this element (and not the nested elements)
    // the attribute name is assumed to be exactly same as property name 'Name'
    OnPropertyChanged(attribute.Name);
  }
}

请注意,Changed 和 Changed 正在冒泡,因此您只能查看 XDocument.Root XElement 或 Model.Element XElement。

有点过于简单了,我希望让你知道它可能是什么样子。现在,.NET 框架就是你的了。

我在以下位置找到了很好的例子:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-26
    • 2018-06-30
    • 1970-01-01
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多