WPF DataGrid单列中使用不同的编辑控件

4

我正在开发一个WPF 4.0应用程序,需要创建一个包含文本框或下拉列表的列的网格,具体根据行来决定。例如:

| Name      |  Value                   | Help                                   |
| PROP1A    | [textbox]                | Description of prop1a                  |
| Prop2A    | [dropdown v]             | Description of prop2a                  |
| Prop3A    | [textbox] [x checkbox]   | Description of prop2a                  |
| Prop4A    | [dropdown v]             | Description of prop2a                  |
| etc...

想法是用户有一张需要输入的数值表格,我们将每个数值的名称和描述与其并列显示。其中一些数值需要使用文本框进行输入,而另一些则需要文本框加复选框,还有一些是下拉菜单。
我的初步想法是将这些值实现为一系列称为“行描述符”的对象,该对象将指定名称、输入类型和帮助信息(即文本),然后使用绑定将集合绑定到 DataGrid 上。基本上,这些将充当视图模型,并且在 DataGrid 中设置值将通过视图模型流向实际的模型(就像 MVVM 应用程序的典型情况一样)。
尽管我查看了可用的文档,但我无法找到任何地方动态更改列类型的方法。现在,我倾向于使用 Grid,手动布置输入(仍然使用 Binding,但逐个绑定每个元素)。然而,这会对我来说需要更多手动工作,因此我想知道是否有一个相对简单的实现我的第一个想法的方法。似乎我应该能够使用 DataGridTemplateColumn 实现某些功能,但我对 WPF 相对较新,不确定如何实现。
2个回答

4
您可以使用模板列实现此操作。
该列显示一个或两个文本框,具体数量取决于行中的数据。
当编辑行时,CellTemplate 通常会被替换为 CellEditingTemplate。
<DataGridTemplateColumn Header="Value" Width="350">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock 
            Text="{Binding EffectiveValue,Mode=OneWay,ValidatesOnDataErrors=True}" 
            ToolTip="{Binding EffectiveValue,Mode=OneWay}"
            TextWrapping="Wrap"
            />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>

    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>


                <TextBlock  Text="Value" Margin="4"/>
                <TextBox 
                Grid.Column="1"
                Text="{Binding ConfigurationValue,ValidatesOnDataErrors=True}" 
                ToolTip="{Binding ConfigurationValue}"
                TextWrapping="Wrap"
                AcceptsReturn="{Binding DataType, Mode=OneWay, 
                                    Converter={StaticResource ResourceKey=StringMatchBooleanConverter}, ConverterParameter=String}"
                gui:FocusAttacher.Focus="True" 
                />

                <TextBlock  Text="Default Value" Grid.Row="1" Margin="4"
                Visibility="{Binding DefaultConfigurationValue, Converter={StaticResource ResourceKey=NullVisibilityConverter}}"
                        />
                <TextBox 
                Grid.Column="1" 
                Grid.Row="1"
                Text="{Binding DefaultConfigurationValue, Mode=OneWay }" 
                ToolTip="{Binding DefaultConfigurationValue, Mode=OneWay}"
                TextWrapping="Wrap"
                IsReadOnly="True" 
                Visibility="{Binding DefaultConfigurationValue, Converter={StaticResource ResourceKey=NullVisibilityConverter}}"

                />

            </Grid>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

这基本上是Cory Larson方法的WPF版本,您在行中拥有所有类型,然后显示或隐藏适当的类型,对吧?(不同之处在于,在您的示例中,这是通过绑定实现的,对吧?) - davidtbernal
我还没有机会查看他的代码。这只是因为我不到一周前才学会如何做的,所以还很新鲜在我的脑海中。 - Jonathan Allen
在C++/CLI中也能实现这个吗? - Astinog

3

我曾在ASP.NET应用程序中使用GridView执行此操作,尽管这是一种不同的技术,但我认为答案是相同的。我所做的就是在每个单元格中添加所有不同类型的控件,但最初将它们保持不可见。

然后,您可以覆盖在网格中将每个项目绑定到行后触发的任何事件(我对WPF也很新,不确定事件是什么),根据您在该行绑定的对象中了解的任何信息更改单元格中适当控件的可见性,然后将控件填充或绑定到适当的值。

当您需要取回值时,它会变得更有趣,但我认为我最终会搜索可见的控件,然后根据控件的类型做出决策。我认为这是您能够完成它的唯一方式,因为我使用过的每个Microsoft网格控件似乎都假设您的列永远不需要不同类型的控件。

我以前在SO上几乎问过同样的问题。这是帖子。也许它会为您开展工作。


2
这真的非常令人沮丧。 - Kajbo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接