2009-12-17 4 views
9

Voici le scénario. Nous utilisons un grand fichier de configuration XML pour l'un de nos produits serveur. Ce fichier est assez bien présenté et est validé par rapport à un fichier XSD.Création d'un éditeur WPF pour un fichier XML basé sur le schéma

Il est temps maintenant de créer une interface graphique de configuration pour maintenir ce fichier et je voudrais plonger dans WPF pour le faire. Je pourrais mettre en forme un formulaire séparé pour chaque section de configuration, refactoring et redistribution chaque fois que nous ajouterions une option au fichier de configuration mais j'espère qu'il y a une façon plus intelligente de le faire.

Étant donné que j'ai déjà une combinaison xml/xsd fortement typée, j'espère qu'il existe une méthode élégante pour créer une interface utilisateur pour l'éditer facilement. Je sais que je pourrais écrire une transformation xml-> xaml mais espérais qu'il y a quelque chose là-bas pour faire le gros du travail pour moi déjà?

Merci à l'avance ..

Répondre

12

Comment je ferais ceci:

Je commence par la construction d'une classe simple vue-modèle qui enroule autour d'un XmlElement et il expose comme une option de configuration. Cette classe pourrait être extrêmement simple, par exemple:

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; } 
    } 
} 

Maintenant, je peux remplir une collection de ElementView objets à partir d'un XmlDocument, ajouter cette collection à ResourceDictionary de la fenêtre, et mettre en forme les objets avec un DataTemplate simple, par exemple:

<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}"/> 

(note:. Plus tard, vous pouvez obtenir la fantaisie, et de définir des sous-classes de OptionView en fonction, par exemple, le type de données sous-jacentes de la XmlElement Ensuite, vous pouvez définir DataTemplate s pour chaque sous-classe, et aussi longtemps que chacun présente l'élément dans une grille à deux colonnes en utilisant ce SharedSizeGroup, la deuxième colonne peut contenir un sélecteur de date, ou des boutons radio, ou tout ce qui est approprié à la sous-classe, et tout Une fois que je me suis mis au travail, ce qui ne serait pas long, je commencerais à étendre la classe OptionView. Par exemple, si votre schéma stocke une étiquette lisible par un humain pour un élément dans un élément (et si ce n'est pas le cas, pourquoi?), Je ferais en sorte que la propriété Name extrait la propriété SchemaInfo de XmlElement , au lieu d'exposer le nom de l'élément sous-jacent.

Évidemment je voudrais ajouter la validation, ainsi j'ajouterais une méthode de validation qui a examiné la propriété SchemaInfo de XmlElement et l'ai interprétée. (En supposant que les éléments que vous validez soient simples, cela ne devrait pas être difficile.) Il y a un million de tutoriels sur la façon d'implémenter la validation dans les applications WPF, donc je n'entrerai pas dans les détails ici.

S'il y a des tonnes d'options de configuration et vous avez une certaine façon intelligente de les grouper en catégories, je construirais une classe de niveau supérieur qui a exposé (au moins) deux propriétés - une chaîne CategoryName propriété et une collection OptionsViews - remplir à partir du document XML, et l'ajouter à ResourceDictionary de la fenêtre. Dans la fenêtre, je le lier à un TabControl, .: par exemple

<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> 

ou à un contrôle de l'élément dont le modèle contenant un objet crée un Expander. Ou quelque chose. (Tout le code garanti non testé!La plus grande partie a été copiée des projets de travail, cependant.)

Si vous n'avez encore rien fait avec WPF, c'est un très bon projet pour commencer. Cela vous exposera aux principes fondamentaux de la liaison de données et des contrôles et validations des éléments, et le résultat final sera quelque chose d'utile et probablement très bien.

Et vous remarquerez que bien que le balisage impliqué dans la création des modèles soit assez verbeux, il n'y a que deux modèles. Le seul code dans l'application (jusqu'à présent) est le code qui expose les XmlElement s à l'interface utilisateur.

+0

Certains y brainfood utiles Robert, merci. –

4

Ici vous allez, nous avons créé un pour votre exigence. Cet outil est entièrement créé en gardant WPF à l'esprit.

http://wpfxmleditor.codeplex.com/

+0

Avez-vous l'intention de faire une version pour votre éditeur? C'est actuellement seulement la source et il n'y a aucune indication de l'état du code (c.-à-d., Est-il complet? Alpha, bêta, stable?) – jlafay

+0

je suis désolé pour la réponse tardive, je n'ai aucun plan pour la libération, vous pouvez télécharger et construire il. – Gomes

0

Pour présenter des configurations XML simples (si les éditeurs personnalisés pour les valeurs ne sont pas obligatoires), vous pouvez lier directement XElement à une vue à l'aide de HierarchicalDataTemplate.

XAML:

<TreeView Grid.IsSharedSizeScope="True" 
      ItemsSource="{Binding Xml.Elements}"> 
    <TreeView.ItemTemplate> 
     <HierarchicalDataTemplate ItemsSource="{Binding Elements}"> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition SharedSizeGroup="Name"/> 
        <ColumnDefinition SharedSizeGroup="Value"/> 
       </Grid.ColumnDefinitions> 
       <Label Content="{Binding Name}" /> 
       <!--Show TextBox only for leaf elements--> 
       <TextBox Grid.Column="1" 
         Text="{Binding Value}" 
         Visibility="{Binding HasElements, 
          Converter={StaticResource reverseBoolToVisibilityConverter}}"/> 
      </Grid> 
     </HierarchicalDataTemplate> 
    </TreeView.ItemTemplate> 
</TreeView> 

vue modèle:

class ConfigViewModel:INotifyPropertyChanged 
{ 
    public XElement Xml { get; private set;} 

    //example of persistence infrastructure 
    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
    public void Load(string fileName) 
    { 
     Xml = XElement.Load(fileName); 
     PropertyChanged(this, new PropertyChangedEventArgs("Xml")); 
    } 
    public void Save(string fileName) 
    { 
     Xml.Save(fileName); 
    } 
} 

There are some good examples for reversed bool to visibility converter.

Questions connexes