从模型动态生成ViewModel

本文关键字:ViewModel 动态 模型 | 更新日期: 2023-09-27 18:29:29

我有一个模型类,它包含一组可以对其执行的命令操作。其想法是,编辑该模型实例的UI可以在运行时动态生成;这是我打算使用动态XAML创建来完成的。到目前为止,一切都很好。

然而,ViewModel完全是另一回事。问题是我的动态UI元素绑定到了什么——它们需要ViewModel中的一个属性来绑定,所以我似乎需要向VM实例动态添加属性,但突然间,这看起来非常混乱。

或者,如果绑定可以发送一个额外的参数,允许我绑定到一个属性,然后使用该参数来决定如何处理该值,那么这将是一个更干净、更简单的解决方案。

或者:一些我不知道或没有考虑过的事情。

从模型动态生成ViewModel

我已经成功地使用ICustomTypeProvider创建了动态视图模型对象,它允许您动态创建可以在运行时构建的绑定点。

http://blogs.msdn.com/b/silverlight_sdk/archive/2011/04/26/binding-to-dynamic-properties-with-icustomtypeprovider-silverlight-5-beta.aspx

不过,请记住,如果您计划做比标准CRUD屏幕更复杂的事情,那么尝试构建一个动态MVVM系统是非常重要的。您失去了附加的属性、附加的行为,并且通过DataTemplates插入WPF好东西(如类型转换器和隐式类型ViewModel渲染)变得有问题。

EDIT:对于WPF,您可能会使用等效的ICustomTypeDescriptor

最简单的选择是对视图模型使用ExpandoObject(或者如果您想添加任何自定义行为,则使用基于DynamicObject的类):

public class MyEditor
{
    public MyEditor()
    {
        Items = new ObservableCollection<ExpandoObject>
        {
            CreateItem(1, "John"),
            CreateItem(2, "Mary"),
            CreateItem(3, "Peter"),
            CreateItem(4, "Sarah")
        };
    }
    private ExpandoObject CreateItem(int id, string name)
    {
        dynamic item = new ExpandoObject();
        item.Id = id;
        item.Name = name;
        return item;
    }
    public ObservableCollection<ExpandoObject> Items { get; private set; }
}

XAML:

    <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Items}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Id" Binding="{Binding Id}"/>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
        </DataGrid.Columns>
    </DataGrid>

如果速度对您有意义,那么您的选择是在运行时发出视图模型类型(请参阅System.Reflection.Emit中的类型)。