3

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

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

在我看来,我将数据模板应用于类型,因此它呈现为圆形或矩形。

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

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

非常感谢

4

2 回答 2

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>可用的形状并使用转换器从形状类型生成一个易于阅读的名称(使用字符串资源文件,完全消除枚举)。

于 2010-08-08T02:12:20.320 回答
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
}
于 2010-08-07T23:21:44.693 回答