2010-08-07 25 views
2

J'essaie d'appliquer le modèle de conception MVVM à une application de création de diagrammes. Dans cette application il y a différents éléments (par exemple un rectangle, un cercle, ...). Je voudrais enregistrer le type d'élément comme une énumération dans mon modèle.MVVM-Pattern pour une application de diagramme avec WPF - Convertir enum en xxxViewModel

Dans mon modelview j'ai fait une classe pour chaque type d'article (rectangleViewMode, circleViewMode, ...).

À mon avis, j'applique un gabarit de données au type, donc il se comporte comme un cercle, ou comme un rectangle.

Le problème est ... comment puis-je convertir l'énumération de mon modèle en xxxViewMode requis? J'ai beaucoup de types et je voudrais une conversion automatique. Je suis nouveau à MVVM et peut-être qu'il y a une meilleure approche ... donc de meilleures solutions sont les bienvenues! :)

Merci beaucoup

+0

Ceci est une question similaire à ici: http://stackoverflow.com/questions/397556/wpf-how-to-bind-radiobuttons-to-an-enum.La classe de convertisseur peut vous aider. –

Répondre

1

Je lis votre question un peu différemment à les autres répondeurs, je ne crois pas que vous cherchez simplement un moyen de lier une énumération à un combo, je pense que vous cherchez un moyen de relier une valeur enum à un type d'objet. Si je suis arrivé ce mal alors arrêtez de lire maintenant :)

Première place: Je ne suis pas sûr que sauver les types de forme comme une énumération (ou en relation avec la forme même à une énumération) est très évolutive. Lisez la suite, et je vais vous expliquer vers la fin.

Relier un type d'élément à un ENUM, ont tout simplement l'élément renvoyer la valeur enum appropriée via une propriété:

public CircleViewMode 
{ 
    public ShapeType Shape { get { return ShapeType.Circle; }} 
} 

public enum ShapeType 
{ 
    Circle, 
    Square, 
    Rectangle, 
    Triangle, 
    FancyShape1, 
    FancyShape2 
} 

Cela signifie que vous ne devez pas utiliser un convertisseur ou un autre mécanisme de traducteur. Si vous voulez ensuite remplir un groupe de ces éléments en un combo alors c'est assez simple - vérifiez l'exemple suivant et insérez des points d'arrêt à l'endroit approprié pour voir comment cela fonctionne. Avec cette approche

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      new Example().Run(); 

      Console.ReadKey(); 
     } 
    } 

    public class Example : INotifyPropertyChanged 
    { 
     public void Run() 
     { 
      var availableShapes = AllMyShapes.Where(x => x.NumberOfSides == 4); 
      AvailableShapes = new List<KeyValuePair<string, Type>> 
       (from Shape s in availableShapes 
       select new KeyValuePair<string, Type>(
                 Enum.GetName(typeof(ShapeType), s.ShapeType) 
                 ,s.GetType() 
                 )); 

      //at this point any combobox you have bound to the AvailableShapes property will now carry a new list of shapes 
     } 

     public List<Shape> AllMyShapes 
     { 
      get 
      { 
       return new List<Shape>() { new Circle(){NumberOfSides=1, ShapeType=ShapeType.Circle} 
              ,new Square(){NumberOfSides=4, ShapeType=ShapeType.Square} 
              ,new Rectangle(){NumberOfSides=4, ShapeType=ShapeType.Rectangle} 
              ,new Triangle(){NumberOfSides=3, ShapeType=ShapeType.Triangle} 
              ,new FancyShape1(){NumberOfSides=10, ShapeType=ShapeType.FancyShape1} 
              ,new FancyShape2(){NumberOfSides=30, ShapeType=ShapeType.FancyShape2} 
             }; 
      } 
     } 

     public List<KeyValuePair<string, Type>> AvailableShapes 
     { 
      get { return _availableShapes; } 
      protected set 
      { 
       _availableShapes = value; 
      } 
     } 

     protected void NotifyPropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 

     private List<KeyValuePair<string, Type>> _availableShapes; 

     public event PropertyChangedEventHandler PropertyChanged; 
    } 


    public abstract class Shape 
    { 
     public int NumberOfSides { get; set; } 
     public ShapeType ShapeType { get; set; } 
    } 

    public class Square : Shape { } 
    public class Rectangle : Shape { } 
    public class Triangle : Shape { } 
    public class Circle : Shape { } 
    public class FancyShape1 : Shape { } 
    public class FancyShape2 : Shape { } 

    public enum ShapeType 
    { 
     Circle, 
     Square, 
     Rectangle, 
     Triangle, 
     FancyShape1, 
     FancyShape2 
    } 
} 

vous aurez un combobox avec de jolis noms de forme lisible par l'homme en elle, et vous pouvez obtenir instantanément le type de forme réelle de l'élément sélectionné. Ce serait une tâche triviale de transformer la classe Example en une base ViewModel abstraite, tout ViewModel dont vous dériveriez alors aura la propriété AvailableShapes.

Mais revenons à mon point d'échelle d'origine - lorsque vous augmentez les types de formes, vous devez également mettre à jour l'énumération. Cela peut poser problème si vous expédiez des bibliothèques de nouvelles formes ou si vous autorisez les utilisateurs à créer les leurs. Il vaut peut-être mieux l'enregistrer sous myShape.GetType().ToString(), ce qui renvoie une valeur de chaîne qui peut ensuite être utilisée pour recréer une instance de l'objet en utilisant la réflexion. Dans l'exemple ci-dessus d'affichage des éléments dans un combo, vous pouvez simplement obtenir un List<Type> des formes disponibles et utiliser un convertisseur pour produire un nom lisible par un humain à partir du type de forme (en utilisant un fichier de ressources chaîne, éliminant complètement l'énumération).

+0

merci beaucoup, vous avez vraiment pris votre temps :) – tundris

+0

@tundris - pas de soucis, c'était un dimanche après-midi pluvieux et je n'avais rien d'autre à faire. J'espère que cela aide :) – slugster

0

En fonction de vos besoins, vous pouvez utiliser une classe de conversion:

(volé How to bind RadioButtons to an enum?)

public class EnumBooleanConverter : IValueConverter 
{ 
    #region IValueConverter Members 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
    string parameterString = parameter as string; 
    if (parameterString == null) 
     return DependencyProperty.UnsetValue; 

    if (Enum.IsDefined(value.GetType(), value) == false) 
     return DependencyProperty.UnsetValue; 

    object parameterValue = Enum.Parse(value.GetType(), parameterString); 

    return parameterValue.Equals(value); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
    string parameterString = parameter as string; 
    if (parameterString == null) 
     return DependencyProperty.UnsetValue; 

    return Enum.Parse(targetType, parameterString); 
    } 
    #endregion 
}