WPF MVVM创建动态控件

use*_*097 8 .net wpf controls dynamic mvvm

WPF MVVM创建动态控件 - 我有一个网格,我有一个工作(你可以说像一个SQL服务器工作)的详细信息.

现在,对于每个工作,可能有'n'个工作变量.当我获取作业的记录时,它获取作为名称 - 值对的Job变量集合,其中value可以是集合或日期时间值,甚至是int或字符串.

现在我想要实现的是: - 如果运行变量是一个日期时间,那么我需要一个datepicker - 如果它是一个int/String我需要一个文本框 - 如果它是一个集合,那么一个组合框. - 它是一个字段然后一个复选框

我不确定如何实现它,因为这些值对于每一项工作都可能有所不同.

Jon*_*Jon 9

我假设您将ItemsControl通过设置其ItemsSource属性将某些表示这些名称/值对的对象放入其中.

您可以使用几种解决方案.

使用DataTemplatewith触发器:

此方法涉及通过YourPropertyType属性将每个对象的"类型"公开为字符串.你将设置ItemTemplate你的ItemsControl,其承载的模板ContentControl.它ContentControl本身将ContentTemplate通过触发器动态选择.

所有这些都可以在XAML中以声明方式完成.

我假设你有进一步的DataTemplates命名DefaultTemplate(可以是空的), ,IntegerTemplate,StringTemplate等勾画出视觉树每种情况.

这将是ItemsControl.ItemTemplate:

<DataTemplate>
    <ContentControl
        x:Name="MyContentControl"
        Content="{Binding}"
        ContentTemplate="{StaticResource DefaultTemplate}"/>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding YourPropertyType}" Value="Integer">
            <Setter TargetName="MyContentControl" Property="ContentTemplate"
                    Value="{StaticResource IntegerTemplate}" />
        </DataTrigger>
        <DataTrigger Binding="{Binding YourPropertyType}" Value="String">
            <Setter TargetName="MyContentControl" Property="ContentTemplate"
                    Value="{StaticResource StringTemplate}" />
        </DataTrigger>
        <!-- and so on -->
    </DataTemplate.Triggers>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)

使用DataTemplateSelector:

这种方法需要代码隐藏,但它不会强制您将每个名称/值对的"类型"公开为字符串,它允许您选择使用哪个模板以及更复杂的逻辑.

它涉及创建一个类作为模板选择器:

class YourObjectDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate DefaultTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        var yourObject = (YourObjectType) item;

        // Get hold of a DataTemplate based on any attribute of item
        var templateToUse = this.DefaultTemplate;

        return templateToUse;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,你需要在某处实例化一个模板选择器(让我们说你的内部UserControl)

<UserControl.Resources>
    <localNamespace:YourObjectDataTemplateSelector
      x:Key="TemplateSelector"
      DefaultTemplate="{StaticResource DefaultTemplate}"
    />
</UserControl.Resources>
Run Code Online (Sandbox Code Playgroud)

请注意,我公开了一个DefaultTemplate属性,YourObjectDataTemplateSelector并将其设置为XAML中的模板.在实践中,您将定义类型的多个属性DataTemplateYourObjectDataTemplateSelector,并将其添加到您的控制的资源字典时,"配置"模板选择.这允许您使用StaticResourceXAML中的标记扩展名直接为每个案例设置模板.

最后,将模板选择器连接到ItemsControl:

<ItemsControl 
  ItemsSource="..."
  ItemTemplateSelector={StaticResource TemplateSelector}"
/>
Run Code Online (Sandbox Code Playgroud)