WPF DataGrid在单个列中的不同编辑控件

时间:2010-07-19 01:01:07

标签: wpf mvvm datagrid

我正在开发一个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...

这个想法是用户有一个他们需要输入的值表,我们会显示每个值的名称和描述。一些值是需要使用文本框输入的数字,而其他值是文本框和复选框,还有一些是下拉列表。

我最初的想法是实现这个基本上是我称之为RowDescriptor的集合,它将指定名称,输入类型和帮助信息(只是文本),然后使用绑定绑定DataGrid的集合。基本上,这些将充当ViewModel,并且设置DataGrid中的值将通过ViewModel流向实际模型(就像MVVM应用程序的典型情况一样)。

当我查看我可用的文档时,我找不到任何讨论如此动态更改列类型的方法。我现在倾向于使用Grid,并手动布局输入(仍使用Binding,但单独绑定每个元素)。这对我来说将是更多的手动工作,所以我想知道是否有一种相对直接的方式来实现我的第一个想法。看起来我应该可以用DataGridTemplateColumn做一些事情,但我对WPF比较陌生,而且我不确定我是怎么做的。

2 个答案:

答案 0 :(得分: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>

答案 1 :(得分:1)

我必须在带有GridView的ASP.NET应用程序中执行此操作,虽然这是一种不同的技术,但我认为答案是相同的。我必须做的只是在每个单元格中添加所有不同类型的控件,但最初让它们不可见。

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

当你需要重新获得值时,它会变得更有趣,但我想我最终会搜索可见的控件,然后根据控件的类型做出决定。我认为这是你能够完成它的唯一方法,因为我从微软使用的每个网格控件似乎都假设你的列永远不需要不同类型的控件。

我之前就问过几乎同样的问题。这是the post。也许它会为你滚动球。