WPF MVVM 创建动态控件

Posted

技术标签:

【中文标题】WPF MVVM 创建动态控件【英文标题】:WPF MVVM Creating Dynamic controls 【发布时间】:2011-07-13 04:18:43 【问题描述】:

- 我有一个网格,在上面我有一份工作(你可以说类似 sql server 工作)的详细信息。

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

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

我不确定如何实现它,因为这些值可能因每项工作而异。

【问题讨论】:

【参考方案1】:

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

您可以使用多种解决方案。

DataTemplate 与触发器一起使用:

此方法涉及通过YourPropertyType 属性将每个对象的“类型”作为字符串公开。您将把ItemsControlItemTemplate 设置为承载ContentControl 的模板。 ContentControl 本身将通过触发器动态选择其 ContentTemplate

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

我假设您还有更多 DataTemplates 命名为 DefaultTemplate(这可以是空的)、IntegerTemplateStringTemplate 等来为每个案例勾勒出可视化树。

这将是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>

使用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;
    

然后,您需要在某处实例化一个模板选择器(假设在您的 UserControl 内部)

<UserControl.Resources>
    <localNamespace:YourObjectDataTemplateSelector
      x:Key="TemplateSelector"
      DefaultTemplate="StaticResource DefaultTemplate"
    />
</UserControl.Resources>

请注意,我从 YourObjectDataTemplateSelector 公开了一个 DefaultTemplate 属性并将其设置为来自 XAML 的模板。在实践中,您将在YourObjectDataTemplateSelector 上定义更多DataTemplate 类型的属性,并在将模板选择器添加到控件的资源字典时“配置”它。这允许您使用来自 XAML 的 StaticResource 标记扩展直接为每个案例设置模板。

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

<ItemsControl 
  ItemsSource="..."
  ItemTemplateSelector=StaticResource TemplateSelector"
/>

【讨论】:

【参考方案2】:

我相信您正在考虑使用某种形式的 Data Templating 和 DataTemplateSelector 来实现您所追求的目标。

【讨论】:

以上是关于WPF MVVM 创建动态控件的主要内容,如果未能解决你的问题,请参考以下文章

WPF随笔之 控件根据设定的显示行数列数填充控件并自适应窗体大小(多绑定MVVM方式实现)

WPF 利用附加属性创建FreezableCollection集合和反射实现控件参数以MVVM模式传递

iOS - 在 MVVM 中动态创建控件

WPF 中动态创建和删除控件

在 WPF MVVM 中添加多个用户控件的最佳控件?

WPF 选项卡控件和 MVVM 选择