WPF MVVM 创建动态控件

发布于 2024-10-21 22:59:15 字数 314 浏览 3 评论 0原文

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

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

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

我不确定如何实现它,因为这些值对于每个作业都可能不同。

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.

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

盛装女皇 2024-10-28 22:59:15

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

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

DataTemplate 与触发器结合使用:

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

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

我假设您还有名为 DefaultTemplate (可以为空)、IntegerTemplateStringTemplate 等的 DataTemplates 等勾勒出每种情况的视觉树。

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

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

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

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

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.

Using a DataTemplate with triggers:

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.

All of this can be done declaratively in XAML.

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.

This would then be the 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>

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;
    }
}

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>

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.

Finally, wire the template selector to your ItemsControl:

<ItemsControl 
  ItemsSource="..."
  ItemTemplateSelector={StaticResource TemplateSelector}"
/>
橘寄 2024-10-28 22:59:15

我相信您正在考虑使用某种形式的数据模板和< a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector.aspx" rel="nofollow">DataTemplateSelector 来实现您的目标。

I believe you are looking at using some form of Data Templating and the DataTemplateSelector to achieve what you are after.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文