2

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

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

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

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

4

2 回答 2

4

我在使用动态视图模型对象方面取得了成功ICustomTypeProvider——它允许您动态创建可以在运行时建立的绑定点。

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

但请记住,如果您打算做比标准 CRUD 屏幕更复杂的事情,尝试构建动态 MVVM 系统并非易事。您丢失了附加属性、附加行为和插入 WPF 好东西,例如类型转换器和通过 DataTemplates 进行隐式类型化的 ViewModel 呈现会成为问题。

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

于 2013-08-28T10:52:14.620 回答
4

最简单的选择是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)。

于 2013-08-28T11:02:37.883 回答