2010-08-02 56 views
1

我正在尝试编写解码一些无符号长整型值的应用程序。每个值的格式用XML表示为:WPF中的XML数据绑定

<Project Name="Project1"> 
<Message Name="a"> 
    <BitField high="31" low="28"> 
    <value>0001</value> 
    <value>1010</value> 
    </Bitfield> 
    <BitField high="27" low="17"> 
    <value>000111101</value> 
    </BitField> 
    <BitField high="16" low="0">100h</BitField> 
</Message> 
</Project> 

现在项目值出现在组合框中。当用户在组合框中选择一个值时,消息类型必须显示在列表框中。然后,当用户在列表框中选择消息类型时,必须显示它们可以容纳的位域和值。现在,当用户为每个位域选择一个值时,最终的双字值必须显示在文本框中。

我遇到了一些例子来解析一个完整的XML,但不涉及到选择。需要你们在这里帮忙。

还有一件事是用户可以在文本框中输入双字值。现在我怎么做这个反向绑定的解码在文本框中的DWORD,并显示相应的消息+值使用上面解释的UI?

UPDATE:现在我已经完成了显示项目值的组合框和显示消息的列表框之间的绑定。接下来我要做的是,当用户在列表框中选择一条消息时,位域必须显示为具有“高”,“低”,“值/ @名称”(此处未显示)的行,然后值(绑定到值/ @名称)作为列。值/ @名称必须显示为组合框。我敢肯定,我可以在dataGrid中做到这一点,但我使用.net 3.5,所以在这里寻找替代品。此外,值文本块必须是可编辑的,以便<值>节点不存在于xml中。最后,我要将“值”列中的条目打包为DWORD。我可以在没有数据网格的情况下在XAML中执行此操作吗?什么是.Net 3.5的数据网格的替代?

+0

什么是C#WPF?这与VB.NET WPF有什么不同? – 2010-08-05 05:32:46

+0

致约翰:WPF与公共语言运行时(CLR)代码集成。 AFAIK这可以从任何.NET语言生成,但肯定是由C#.NET和VB.NET生成的,所以基本上不管使用什么语言,都可以使用相同的功能。 – 2010-08-08 15:48:18

回答

2

这里有两个不同的问题 - XML解析问题和转换问题。

对于绑定工作,您需要将XML解析为表示其值的类。对于转换问题,我将您指向TypeConverters的概念,这些概念非常简单易用。对于XML解析问题,我想强调LINQ-to-XML,我认为这是蜜蜂跪下的问题。它的几行可以重构来自XML源的最复杂的对象图。对于Project/Message/BitField的例子,我已经部分实现了一个解决方案,可以给你这个模式。

请注意“LoadFromXml”方法。这使用填充对象图的linq-to-xml表达式。有一件事是,在你的XML源此查询的变化是,它期待着收集节点(即或)通过收集节点(即)

public class Project 
    { 
     public string Name { get; set; } 
     public List<Message> MessageCollection = new List<Message>(); 

     public void LoadFromXml(string xmlString) 
     { 
      // From System.Xml.Linq 
      XDocument xDocument = XDocument.Parse(xmlString); 

      // The following assumes your XML is well formed, is not missing attributes and has no type conversion problems. In 
      // other words, there is (almost) zero error checking. 
      if (xDocument.Document != null) 
      { 
       XElement projectElement = xDocument.Element("Project"); 

       if (projectElement != null) 
       { 
        Name = projectElement.Attribute("Name") == null ? "Untitled Project" : projectElement.Attribute("Name").Value; 

        MessageCollection = new List<Message> 
         (from message in xDocument.Element("Project").Elements("Messages") 
         select new Message() 
           { 
            Name = message.Attribute("Name").Value, 
            BitfieldCollection = new List<BitField> 
             (from bitField in message.Elements("Bitfields") 
              select new BitField() {High = int.Parse(bitField.Attribute("High").Value), Low = int.Parse(bitField.Attribute("Low").Value)}) 
           } 
         ); 
       } 
      } 
     } 
    } 

    public class Message 
    { 
     public string Name { get; set; } 
     public List<BitField> BitfieldCollection = new List<BitField>(); 
    } 

    public class BitField 
    { 
     public int High { get; set; } 
     public int Low { get; set; } 
     public List<string> ValueCollection = new List<string>(); 
    } 
1

你一定要牢记模型的分离包围以及该模型的视图和外部表示。根据实际的XML的大小以及这种类型的API可以让你感觉舒适,可以使用几种完全不同的方式来读取XML并将其转换为实际的对象,然后将其作为您的UI的模型。牢记这种分离很重要。

我会假定你的XML是来自其他处理的实际数据 - 这意味着将会有很多项目标签,有很多消息标签,并且位域跨度不同于消息。如果这个假设是错误的,并且位域跨度对于整个应用程序或者一个大文件中的所有消息都是固定的,那么您可以节省一些时间和空间。

因此,假设所有东西都是可变的,那么从标签获取值的最快方法就是创建XPathDocumen并通过XPath进行选择,然后您可以保留字符串或配置文件。例如,这会给你所有的价值标签(现称为节点)

//Project/Message/BitField/Value 

,并因为对节点的对象有父指针,你可以去收集共享父(到一个列表或数组)的所有值,则使物体对于父级(BitField),保留它并确保它具有来自XmlNode的Parent指针。一旦你拥有了所有的BitField对象,你就可以进行类似的扫描,然后分组到他们的父母(Message)中,并再次获得Project-s。这只是一种方法,您可以使用较短的XPath来说明从BitField开始收集并自行获取子项。

您还可以制作一些普通类来逐字表示XML标记(每个字段一个数据成员,每个标记一个类),然后为XmlSerialization设置属性。这将需要一些试验来确定名称是否正确,但是你可以通过函数调用来“反序列化”整个文件,并从.NET接收数组或数组的数组:。

如果您的文件非常非常大,那么您可能必须使用XmlTextReader并从上到下扫描文件 - 与XPath选择完全相反(XmlTextReader是解析的最轻方式,不会创建吨的额外的对象,但你必须在几个外观上迭代它,并且总是从父母到孩子“走路”,因为它是单向的)。

如果您有时间进行UI实验,可能值得尝试构建一个包含3个组合框和一个文本框然后列出这些框的边界框 - 以便您拥有更大的灵活性,例如:不必遵守电网的机制。

哦,如果您对XML格式有任何影响,尝试让ppl始终将该值放入值标记中,即使它只是一个。 XML文件将会更长一些,但是您的处理将会简化。

1

这可以使用数据绑定和XMLReaders完成。首先创建你的用户界面,最好在父面板内部(这样我们可以设置面板的数据上下文,而子控件将全部继承这个上下文)。

接下来创建一个自定义类(我们称之为Project)。确保此类中的每个字段都更新PropertyDependencyInfo,否则数据绑定将无法工作。

然后将UI控件的Content或Itemssource属性绑定到Project类的字段。

然后,使用XMLReader类或XPathReader类创建读取XML的代码。然后,当您访问文件中的数据时,设置一个新的Project对象的字段以匹配您想要读取的数据。

一旦Project对象已被实例化并且XML的值正确地分配给它,请将父级Panel从UI的DataContext属性设置为您的Project对象。所有的UI字段都应该更新。

如果您随后需要加载不同的文件,您只需使用不同的文件名重复XML读取。

至于你的更新:行和列可以使用管理以下任一操作:

表格/ UniformGrid控制其RowDefinition和ColumnDefinition儿童创建并在运行时修改,以管理增加和减少的数目字段

或者:一组StackPanel,每列一列(因为列数永远不会改变)。您可以直接将组合框添加到您的值/ @名称列的StackPanel,或者您可以修改StackPanel的ItemsTemplate(如果它有一个,我无法到达机器以检查此刻)。

这个问题应该可以分成几个子问题,因为它涵盖了一系列的主题,如果有问题专门针对这些问题定制问题,那么您更可能得到问题每个方面的详细答案。