WPF MVVM 创建动态控件 [英] WPF MVVM Creating Dynamic controls
问题描述
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.
推荐答案
我假设您将通过设置 将表示这些名称/值对的某种对象放入
属性.ItemsControl
ItemsSource
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
属性将每个对象的类型"作为字符串公开.您将ItemsControl
的ItemTemplate
设置为承载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
(这可以是空的)、IntegerTemplate
、StringTemplate
等来勾勒出每种情况的可视化树.
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屋!