Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 使用WPF根据绑定属性动态显示控件_.net_Wpf - Fatal编程技术网

.net 使用WPF根据绑定属性动态显示控件

.net 使用WPF根据绑定属性动态显示控件,.net,wpf,.net,Wpf,我有一个数据库数据类型的属性(char,DateTime,int,float等),我想更改用于输入所选类型值的控件。因此,对于文本值,我需要一个文本框,对于日期值,我需要一个日期选择器 我考虑这样做的一种方法是在我的表单上设置每个控件中的一个,并使用适当的IValueConverter实现设置它们的Visibility。我知道这会起作用,但它会产生很多代码,感觉不是很好 另一种方法是使用ContentPresenter并将其内容设置为样式和DataTriggers,但我无法让它工作 <St

我有一个数据库数据类型的属性(
char
DateTime
int
float
等),我想更改用于输入所选类型值的控件。因此,对于文本值,我需要一个
文本框
,对于日期值,我需要一个
日期选择器

我考虑这样做的一种方法是在我的表单上设置每个控件中的一个,并使用适当的
IValueConverter
实现设置它们的
Visibility
。我知道这会起作用,但它会产生很多代码,感觉不是很好

另一种方法是使用
ContentPresenter
并将其内容设置为
样式
DataTriggers
,但我无法让它工作

<Style x:Key="TypedValueHelper" TargetType="{x:Type ContentPresenter}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=DataType}" Value="Char">
            <Setter Property="Content" Value="???"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=DataType}" Value="Date">
            <Setter Property="Content" Value="???"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=DataType}" Value="Integer">
            <Setter Property="Content" Value="???"/>
        </DataTrigger>
    </Style.Triggers>
</Style>


如果有人可以填写我的“?”或提供更好的解决方案,请填写

我会研究数据模板。例如:

<DataTemplate DataType="{x:Type local:Input}">
    <local:InputControl DataContext="{Binding}" />
</DataTemplate>

<DataTemplate DataType="{x:Type data:VideoData}">
    <local:VideoControl DataContext="{Binding}"></local:VideoControl>
</DataTemplate>

您可以将样式与setter和数据模板相结合。虽然我认为
ContentPresenter
不是样式的正确控件,因为它没有模板,但它基本上是在代码中开始的

创建如下样式:

<Style x:Key="TypedValueHelper" TargetType="{x:Type ContentControl}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=DataType}" Value="Char">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <TextBox Text="{Binding Path=.}" />
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=DataType}" Value="Integer">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <Slider Maximum="100" Minimum="0" Value="{Binding Path=.}"
                                         Orientation="Horizontal" />
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>
<ContentControl Content="{Binding Path=ReferenceToYourViewModel}" ContentTemplateSelector="{DynamicResource MyTemplateSelector}"/>

虽然
样式
解决方案可能有效,但实现动态内容行为的正确方法是使用Sdry建议的数据模板。但是,您将使用枚举来确定要使用哪个DataTemplate,这本质上意味着您希望将单个类型映射到多个DataTemplates。此问题由
DataTemplateSelector
类解决,以下描述直接来自MSDN:

通常,当同一类型的对象有多个DataTemplate,并且希望提供自己的逻辑来根据每个数据对象的属性选择要应用的DataTemplate时,可以创建DataTemplateSelector

动态内容应该由
ContentControl
托管,如下所示:

<Style x:Key="TypedValueHelper" TargetType="{x:Type ContentControl}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=DataType}" Value="Char">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <TextBox Text="{Binding Path=.}" />
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=DataType}" Value="Integer">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <Slider Maximum="100" Minimum="0" Value="{Binding Path=.}"
                                         Orientation="Horizontal" />
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>
<ContentControl Content="{Binding Path=ReferenceToYourViewModel}" ContentTemplateSelector="{DynamicResource MyTemplateSelector}"/>
然后,正如您所期望的,以下是要从中选择的数据模板:

<DataTemplate x:Key="CharDataTemplate" DataType="{x:Type YourViewModel}">Put Your Xaml Here</DataTemplate>
<DataTemplate x:Key="DateDataTemplate" DataType="{x:Type YourViewModel}">Put Your Xaml Here</DataTemplate>
<DataTemplate x:Key="IntegerDataTemplate" DataType="{x:Type YourViewModel}">Put Your Xaml Here</DataTemplate>
将您的Xaml放在这里
把你的Xaml放在这里
把你的Xaml放在这里

这样,将根据视图模型的
DataType
属性选择适当的
DataTemplate
。在我看来,这比使用
可见性
或样式要干净得多

我不确定这是否适用于我,因为我没有使用实际的“类型”来选择控件,我使用的是作为ViewModel上的属性公开的枚举值。我不确定我是否可以共享我的代码,因为有很多依赖项。事实上,我的实际问题比我说的要复杂一点。我很确定你的解决方案会对我有用,我刚刚遇到一个问题,我试图将ContentControl的内容设置为{Binding},而不是{Binding MyValue},这意味着WPF在内容控件中加载我的ViewModel的视图,并递归地继续运行……啊,我明白了。您是否尝试过{Binding Path=.}?已排序!我必须将的日期类型设置为ViewModel的类型。我想这会在ViewModel类型和要显示的视图之间创建一个局部范围的绑定。再次感谢!!