基于架构为 XML 文件创建 WPF 编辑器 [英] Creating a WPF editor for XML file based on schema

查看:42
本文介绍了基于架构为 XML 文件创建 WPF 编辑器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是场景.我们为我们的服务器产品之一使用大型 XML 配置文件.该文件布局合理,并针对 XSD 文件进行了验证.

Here's the scenario. We use a large XML configuration file for one of our server products. This file is fairly well layed out and is validated against an XSD file.

现在是构建用于维护此文件的配置 GUI 的时候了,我想深入研究 WPF 来完成它.我可以为每个配置部分布置一个单独的表单,每次向配置文件添加选项时都进行重构和重新分发,但我希望有更聪明的方法来做到这一点.

It's time now though to build a configuration GUI for maintaining this file and I would like to dive into WPF to do it. I could lay out a seperate form for each config section, refactoring and redistributing every time we add an option to the config file but I'm hoping there is a more clever way of doing this.

因为我已经有了一个强类型的 xml/xsd 组合,我希望有一种优雅的方法来构建一个 UI 来轻松地编辑它.我知道我可以编写一个 xml->xaml 转换,但希望有什么东西可以帮我完成繁重的工作?

Since I already have a strongly typed xml/xsd combination I am hoping there is an elegant method for building a UI to edit this easily enough. I know I could write an xml->xaml transformation but was hoping there is something out there to do the heavy lifting for me already?

提前致谢..

推荐答案

我会怎么做:

我首先构建一个简单的视图模型类,该类封装了 XmlElement 并将其作为配置选项公开.这个类可以非常简单,例如:

I'd start by building a simple view-model class that wraps around an XmlElement and exposes it as a configuration option. This class could be extremely simple, e.g.:

public class OptionView
{
   private XmlElement XmlElement;
   public OptionView(XmlElement xmlElement)
   {
      XmlElement = xmlElement;
   }
   public string Name { get { return XmlElement.Name; } }
   public string Value 
   { 
      get { return XmlElement.InnerText; } 
      set { XmlElement.InnerText = value; }
   }
}

现在我可以从 XmlDocument 填充 ElementView 对象的集合,将该集合添加到窗口的 ResourceDictionary,并使用一个简单的DataTemplate,例如:

Now I can populate a collection of ElementView objects from an XmlDocument, add that collection to the window's ResourceDictionary, and format the objects with a simple DataTemplate, e.g.:

<DataTemplate x:Key="OptionViewTemplate" DataType={x:Type local:OptionView}>
   <Grid>
       <Grid.ColumnDefinitions>
          <ColumnDefinition SharedSizeGroup="Name"/>
          <ColumnDefinition SharedSizeGroup="Value"/>
       </Grid.ColumnDefinitions>
       <Label Content="{Binding Name}" Grid.Column="0"/>
       <TextBox Text="{Binding Value}" Grid.Column="1"/>
   </Grid>
</DataTemplate>
...
<ItemsControl Grid.IsSharedSizeScope="True"
    ItemsSource="{DynamicResource OptionCollection}"/>

(注:后面可以花心思,根据底层XmlElement的数据类型等来定义OptionView的子类.然后就可以定义DataTemplate 用于每个子类,只要每个子类都使用 SharedSizeGroup 在两列网格中显示项目,第二列可以包含日期选择器或单选按钮,或者任何适合子类的东西,它都会在运行时整齐地布置.)

(Note: Later, you can get fancy, and define subclasses of OptionView based on, for instance, the data type of the underlying XmlElement. Then you can define DataTemplates for each subclass, and as long as each presents the item in a two-column grid using that SharedSizeGroup, the second column can contain a date picker, or radio buttons, or whatever is appropriate to the subclass, and it'll all get neatly laid out at runtime.)

一旦我开始工作,这不会花很长时间,我将开始扩展 OptionView 类.例如,如果您的架构在 xs:annotation 元素中存储元素的人类可读标签(如果不是,为什么不呢?),我会制作 Name 属性从 XmlElementSchemaInfo 属性中提取出来,而不是暴露底层元素名称.

Once I got that working, which wouldn't take long, I'd start extending the OptionView class. For instance, if your schema is storing a human-readable label for an element in an xs:annotation element (and if it isn't, why not?), I'd make the Name property extract that out of the XmlElement's SchemaInfo property, instead of exposing the underlying element name.

显然我想添加验证,所以我添加了一个验证方法来检查 XmlElementSchemaInfo 属性并解释它.(假设您要验证的元素是简单的内容,那应该不难.)关于如何在 WPF 应用程序中实现验证的教程有上百万篇,因此我不会在此详细介绍.

Obviously I'd want to add validation, so I'd add a validation method that examined the XmlElement's SchemaInfo property and interpreted it. (Assuming that the elements you're validating are simple content, that shouldn't be hard.) There's a million tutorials on how to implement validation in WPF applications, so I won't go into too much detail here.

如果有大量的配置选项并且你有一些聪明的方法将它们分组到类别中,我会构建一个更高级别的类来公开(至少)两个属性 - 一个字符串 CategoryName 属性和一个 OptionsViews 集合 - 从 XML 文档填充它,并将其添加到窗口的 ResourceDictionary.在窗口中,我将其绑定到 TabControl,例如:

If there are tons of configuration options and you have some intelligent way of grouping them into categories, I'd build a higher level class that exposed (at least) two properties - a string CategoryName property and an OptionsViews collection - populate it from the XML document, and add it to the window's ResourceDictionary. Within the window, I'd bind it to a TabControl, e.g.:

<TabControl ItemsSource="{DynamicResource OptionCategories}">
   <TabControl.ItemContainerStyle>
      <Style TargetType="{x:Type CategoryView}">
         <Setter Property="Header" Value="{Binding Path=CategoryName}"/>
         <Setter Property="Content" Value="{Binding Path=OptionsViews}"/>
         <Setter Property="ContentTemplate" Value="{StaticResource OptionViewTemplate}"/>
      </Style>
   </TabControl.ItemContainerStyle>
</TabControl>

或某些项目控件,其项目容器模板创建了一个 Expander.或者其他的东西.(所有代码保证未经测试!不过,大部分代码是从工作项目中复制出来的.)

Or to some item control whose item container template creates an Expander. Or something. (All code guaranteed untested! Most of it was copied out of working projects, though.)

如果您之前没有对 WPF 做过任何事情,那么这是一个非常好的开始项目.它将向您展示数据绑定以及项目控制和验证的基础知识,最终结果将是有用的并且可能看起来相当不错.

If you haven't done anything with WPF before, this is a pretty good project to start on. It'll expose you to the fundamentals of data binding and items controls and validation, and the end result will be something that's useful and probably looks pretty good.

您会注意到,虽然创建模板所涉及的标记非常冗长,但只有两个模板.应用程序中的唯一代码(到目前为止)是将 XmlElement 暴露给 UI 的代码.

And you'll notice that while the markup involved in creating the templates is pretty verbose, there are only two templates. The only code in the application (so far) is the code that exposes the XmlElements to the UI.

这篇关于基于架构为 XML 文件创建 WPF 编辑器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆