2010-08-07 3 views
2

Я пытаюсь применить шаблон проектирования MVVM к приложению диаграмм. В этом приложении есть разные элементы (например, прямоугольник, круг, ...). Я хотел бы сохранить тип элемента как перечисление в моей модели.MVVM-шаблон для диаграммного приложения с WPF - преобразование enum в xxxViewModel

В моем представлении модели я создал класс для каждого типа элемента (rectangleViewMode, circleViewMode, ...).

В моем представлении я применяю шаблон данных к типу, поэтому он отображается как круг или как прямоугольник.

Проблема в том, как ... я могу преобразовать перечисление в моей модели в требуемый xxxViewMode? У меня много типов, и я бы хотел автоматическое преобразование.

Я новичок в MVVM, и, возможно, есть лучший подход ... поэтому лучшие решения приветствуются! :)

Большое спасибо

+0

Это похоже на вопрос: http://stackoverflow.com/questions/397556/wpf-how-to-bind-radiobuttons-to-an-enum.Класс конвертера может вам помочь. –

ответ

1

Я прочитал ваш вопрос немного по-другому, чтобы другие ответчики, я не верю, что вы просто ищете способ привязки перечисления к комбо, я думаю, вы ищете способ связать значение перечисления с типом объекта. Если у меня это получилось, то перестаньте читать сейчас :)

Прежде всего: Я не уверен, что сохранение типов фигур в качестве перечисления (или даже привязка формы к перечислению) очень масштабируемо. Читайте дальше, и я объясню до конца.

Чтобы связать тип элемента для перечисления, просто элемент возвращает соответствующее значение перечисления через свойство:

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

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

Это означает, что вы не должны использовать преобразователь или другой механизм переводчика. Если вы хотите заполнить кучу этих данных в комбо, это довольно просто - проверьте этот следующий образец и вставьте точки останова в соответствующее место, чтобы посмотреть, как это работает.

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

При таком подходе вы будете иметь выпадающий с хорошими человеческими именами читаемой формы в нем, и вы можете мгновенно получить фактический тип формы выбранного элемента. Было бы тривиальной задачей превратить класс Example в абстрактную базу ViewModel, любая ViewModel, которую вы затем выведете из нее, будет иметь свойство AvailableShapes.

Но вернемся к исходной точке масштабируемости - по мере того, как вы увеличиваете типы фигур, вам также необходимо обновить перечисление. Это может быть проблематично, если вы отправляете библиотеки новых форм или позволяете пользователям создавать свои собственные. Возможно, вам лучше сохранить его как myShape.GetType().ToString(), который возвращает строковое значение, которое затем можно использовать для воссоздания экземпляра объекта с использованием отражения. В приведенном выше примере показа элементов в комбо вы можете просто получить List<Type> доступных фигур и использовать конвертер для создания приятного для чтения человека имени из типа формы (используя файл строковых ресурсов, полностью исключая перечисление).

+0

Большое вам спасибо, вы действительно потратили свое время там :) – tundris

+0

@tundris - не беспокойтесь, это был дождливый воскресный день, и мне больше нечего было делать. Надеюсь, поможет :) – slugster

0

В зависимости от ваших потребностей, вы можете использовать конвертер класс:

(украденного из 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 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^