使用WPF的Diagraming应用程序的MVVM模式 - 将枚举转换为xxxViewModel

时间:2010-08-07 23:17:48

标签: mvvm type-conversion diagramming

我正在尝试将MVVM设计模式应用于图表应用程序。在此应用程序中有不同的项目(例如矩形,圆形......)。我想将项目类型保存为模型中的枚举。

在我的模型视图中,我为每个项目类型(rectangleViewMode,circleViewMode,...)创建了一个类。

在我的视图中,我将数据模板应用于该类型,因此它呈现为圆形或矩形。

问题是......如何将模型中的枚举转换为需要的xxxViewMode?我有很多类型,我想要自动转换。

我是MVVM的新手,也许有更好的方法......所以欢迎更好的解决方案! :)

非常感谢

2 个答案:

答案 0 :(得分: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>可用形状并使用转换器从形状类型生成一个漂亮的人类可读名称(使用字符串资源文件,消除完全枚举。)

答案 1 :(得分: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
}