WPF MVVM 创建动态控件 [英] WPF MVVM Creating Dynamic controls

查看:29
本文介绍了WPF MVVM 创建动态控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

WPF MVVM 创建动态控件 - 我有一个网格,我在该网格上有一个作业(你可以说类似于 sql server 作业)的详细信息.

WPF MVVM Creating Dynamic controls - I have a grid on which I have a job's (you can say something like a sql server job) details.

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

Now for every job there could be 'n' number of job variables. When I fetch the record for a job it gets this collection of Job variables which are Name-value pair, where value could be a collection or a datetime value or even an int or a string.

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

Now what I am trying to achieve here is : -- If the run variable is a datetime then I need a datepicker -- If it is a int/String I need a text box -- If it is a collection then a combo box . -- it it is a bit field then a check box

我不确定如何实现它,因为每个工作的这些值可能不同.

I am not sure how to achieve it since these values can differ for every single job.

推荐答案

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

I am assuming that you will put some kind of objects representing these name/value pairs into an ItemsControl by setting its ItemsSource property.

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

There are a couple of solutions you can use.

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

This approach involves exposing the "type" of each of your objects through the YourPropertyType property as a string. You will set the ItemTemplate of your ItemsControl to a template which hosts a ContentControl. The ContentControl itself will have its ContentTemplate selected dynamically with triggers.

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

All of this can be done declaratively in XAML.

我假设你有进一步的 DataTemplates 名为 DefaultTemplate(这可以是空的)、IntegerTemplateStringTemplate等来勾勒出每种情况的可视化树.

I am assuming you have further DataTemplates named DefaultTemplate (this can be empty), IntegerTemplate, StringTemplate, etc to sketch out the visual tree for each case.

这就是 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:

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

Using a DataTemplateSelector:

This approach requires code-behind, but it does not force you to expose the "type" of each name/value pair as a string and it allows you to choose which template to use with much more complex logic.

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

It involves creating a class to be the template selector:

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 内)

Then, you need to instantiate a template selector somewhere (let's say inside your UserControl)

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

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

Notice that I exposed a DefaultTemplate property from YourObjectDataTemplateSelector and set that to a template from XAML. In practice, you would define more properties of type DataTemplate on YourObjectDataTemplateSelector, and "configure" the template selector when adding it into the resource dictionary of your control. This allows you to directly set the templates for each case using the StaticResource markup extension from XAML.

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

Finally, wire the template selector to your ItemsControl:

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

这篇关于WPF MVVM 创建动态控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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