带有 WPF 的图表应用程序的 MVVM 模式 - 将枚举转换为 xxxViewModel [英] MVVM-Pattern for a Diagraming Application with WPF - Convert enum to xxxViewModel

查看:55
本文介绍了带有 WPF 的图表应用程序的 MVVM 模式 - 将枚举转换为 xxxViewModel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to apply the MVVM design pattern to a diagramming application. In this application there are different items (for example a rectangle, a circle,...). I would like to save the item type as an enum in my model.

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

In my modelview I made a class for every item type (rectangleViewMode, circleViewMode,...).

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

On my view I apply a data template to the type, so it renders like a circle, or like a rectangle.

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

The problem is...how can I convert the enum in my model to the requiered xxxViewMode? I have a lot of types and I would like an automatic conversion.

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

I'm new to MVVM and maybe there is a better approach...so better solutions are welcome! :)

非常感谢

推荐答案

我对您的问题的理解与其他回答者略有不同,我不相信您只是在寻找一种将枚举绑定到组合的方法,我认为您正在寻找一种将枚举值与对象类型相关联的方法.如果我弄错了,请立即停止阅读:)

I read your question a little differently to the other answerers, i don't believe you are just looking for a way to bind an enum to a combo, i think you are looking for a way to relate an enum value to an object type. If i got this wrong then stop reading now :)

首先:我不确定将形状类型保存为枚举(甚至将形状与枚举关联)是否具有很强的可扩展性.继续阅读,我会在最后解释.

First up: I'm not sure that saving the shape types as an enumeration (or even relating the shape to an enumeration) is very scalable. Read on, and i'll explain towards the end.

要将项目类型与枚举相关联,只需让项目通过属性返回适当的枚举值:

To relate an item type to an enum, just have the item return the appropriate enum value via a property:

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

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

这意味着您不必使用转换器或其他转换器机制.如果您想将其中的一堆填充到一个组合中,那么它非常简单 - 检查以下示例并在适当的位置插入断点以查看它是如何工作的.

This means that you don't have to employ a converter or another translator mechanism. If you want to then populate a bunch of these into a combo then it is quite simple - check this following sample and insert breakpoints at the appropriate spot to see how it works.

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 属性.

With this approach you will have a combobox with nice human readable shape names in it, and you can instantly get the actual shape type of the selected item. It would be a trivial task to turn the class Example into an abstract base ViewModel, any ViewModel you then derive from it will have the AvailableShapes property.

但回到我最初的可扩展性观点 - 随着您增加形状类型,您还需要更新枚举.如果您提供新形状库或允许用户创建自己的形状库,这可能会出现问题.您最好将其保存为 myShape.GetType().ToString(),它返回一个字符串值,然后可以使用该值使用反射重新创建对象的实例.在上面显示组合中项目的示例中,您可以获得可用形状的 List 并使用转换器从形状类型中生成一个很好的人类可读的名称(使用字符串资源文件,完全消除枚举).

But back to my original point of scalability - as you increase the shape types you also need to update the enumeration. This could be problematic if you ship libraries of new shapes or allow users to create their own. You may be better off saving it as myShape.GetType().ToString(), which returns a string value that can then be used to recreate the an instance of the object using reflection. In the above example of showing the items in a combo, you could just get a List<Type> of the available shapes and use a converter to produce a nice human readable name from the shape type (using a string resource file, eliminating the enumeration altogether).

这篇关于带有 WPF 的图表应用程序的 MVVM 模式 - 将枚举转换为 xxxViewModel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆