在 WPF 数据网格、组合框模板列上单击编辑

Posted

技术标签:

【中文标题】在 WPF 数据网格、组合框模板列上单击编辑【英文标题】:Single click edit on WPF datagrid , combobox template column 【发布时间】:2012-05-05 08:11:30 【问题描述】:

我有一个包含三列的网格:

    好记的名字 大陆名称 国家/地区名称

第一列是可编辑的文本框列。第二列是显示大陆列表的组合框。第 3 列是一个组合框,显示基于在第 2 列中选择的大陆的国家列表。我想为这些列实现单击。我尝试了此链接中给出的解决方案 Single click edit in WPF DataGrid

但这仅适用于第一列,而不适用于其他两个 (DataGridTemplateColumn) 列。

这怎么可能。请建议。示例 XAML 和数据描述如下。

<DataGrid Grid.Row="1" VerticalAlignment="Top"
                                   ItemsSource="Binding Path=GeographyData,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged"
                                  Style="StaticResource DataGridStyleNormal">
                            <DataGrid.Columns>
                                <DataGridTextColumn Width="*" Header="Friendly name" Binding="Binding Path=FriendlyName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged"/>
                                <!--FilterDef -->
                                <DataGridTemplateColumn Width="*"
                                                        Header="Continents">
                                    <DataGridTemplateColumn.CellEditingTemplate>
                                        <DataTemplate>
                                            <ComboBox SelectedValue="Binding ContinentId, Mode=TwoWay"
                                                      SelectedValuePath="ID"
                                                      DisplayMemberPath="Name"
                                                      ItemsSource="Binding Path=DataContext.ContinentsAndCountries,Mode=OneWay,UpdateSourceTrigger=PropertyChanged,RelativeSource=RelativeSource Mode=FindAncestor,AncestorType=x:Type DataGrid"/>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellEditingTemplate>
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <TextBlock>
                                               <TextBlock.Text>
                                                    <MultiBinding Converter="StaticResource ContinentCaptionConverter">
                                                          <Binding Path="ContinentId"/>
                                                          <Binding Path="DataContext.ContinentsAndCountries" RelativeSource="RelativeSource Mode=FindAncestor,AncestorType=x:Type DataGrid"/>
                                                        </MultiBinding>
                                                </TextBlock.Text>
                                            </TextBlock>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>
                                <!--Level-->
                                <DataGridTemplateColumn Width="*"
                                                        Header="Countries">
                                    <DataGridTemplateColumn.CellEditingTemplate>
                                        <DataTemplate>
                                            <ComboBox SelectedValue="Binding CountryId, Mode=TwoWay"
                                                      SelectedValuePath="ID"
                                                      DisplayMemberPath="Name">
                                                <ComboBox.ItemsSource>
                                                    <MultiBinding Converter="StaticResource CountryValuesConverter">
                                                        <Binding Path="DataContext.ContinentsAndCountries" RelativeSource="RelativeSource Mode=FindAncestor,AncestorType=x:Type DataGrid"/>
                                                        <Binding Path="ContinentId"/>
                                                    </MultiBinding>
                                                </ComboBox.ItemsSource>
                                            </ComboBox>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellEditingTemplate>
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <TextBlock>
                                               <TextBlock.Text>
                                                    <MultiBinding Converter="StaticResource CountryCaptionConverter">
                                                            <Binding Path="DataContext.ContinentsAndCountries" RelativeSource="RelativeSource Mode=FindAncestor,AncestorType=x:Type DataGrid"/>
                                                            <Binding Path="ContinentId"/>
                                                            <Binding Path="CountryId"/>
                                                        </MultiBinding>
                                                </TextBlock.Text>
                                            </TextBlock>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>
                            </DataGrid.Columns>
                        </DataGrid>

注意:数据“ContinentsAndCountries”是主从数据的可观察集合。

吉里哈

【问题讨论】:

也许this answer 对你有帮助。 那就看看Tabbing from cell to cell does not set focus on control吧。 不起作用。我想它与此链接***.com/questions/3426765/… 中的功能相同 我通过设置组合框加载事件来做到这一点 private void Combobox_Loaded(object sender, RoutedEventArgs e) if (sender != null) ComboBox cmb = sender as ComboBox; cmb.IsDropDownOpen = true; 很好。然后将其作为答案发布并接受。 【参考方案1】:

我通过设置组合框加载事件来做到这一点

private void DataGridComboboxTemplate_Loaded(object sender, RoutedEventArgs e)
    
        if (sender != null)
        
            ComboBox cmb = sender as ComboBox;
            cmb.IsDropDownOpen = true;
        
    

【讨论】:

【参考方案2】:

对不起他的死灵;我终于想出了如何制作真正的单击 UX。您必须拦截 DataGridCell 的 OnGotFocus 事件,将单元格的模式设置为 IsEditing,然后在 CellEditingTemplate 中拦截 Actor 控件的 Loaded 事件:

<Window.Resources>
    <Style
        x:Key="AutoEditModeOnClick"
        TargetType="x:Type DataGridCell">

        <EventSetter Event="GotFocus" Handler="DataGridCell_OnGotFocus" />
    </Style>
</Window.Resources>

<DataGrid.Columns>
    <DataGridTemplateColumn
        CellStyle="StaticResource AutoEditModeOnClick"
        Header="Score">

        <!-- Example with ComboBox -->

        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <!-- Some more XAML -->
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>

        <DataGridTemplateColumn.CellEditingTemplate>
            <DataTemplate>
                <!-- Some more XAML -->
                <ComboBox
                    DisplayMemberPath="Description"
                    SelectedValuePath="RecordID"
                    SelectedValue="Binding Score,
                        TargetNullValue=0,
                        UpdateSourceTrigger=PropertyChanged"
                    ItemsSource="Binding DataContext.ScoreOptions,
                        RelativeSource=RelativeSource
                            AncestorType=x:Type DataGrid"
                    Loaded="Combobox_Loaded"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellEditingTemplate>
    </DataGridTemplateColumn>

    <DataGridTemplateColumn
        CellStyle="StaticResource AutoEditModeOnClick"
        Header="Comment">

        <!-- Example with TextBox -->

        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <!-- Some more XAML -->
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>

        <DataGridTemplateColumn.CellEditingTemplate>
            <DataTemplate>
                <!-- Some more XAML -->
                <TextBox
                    Loaded="TextBox_Loaded"
                    Text="Binding Comment,
                        UpdateSourceTrigger=LostFocus"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellEditingTemplate>
    </DataGridTemplateColumn>
</DataGrid.Columns>

在您的代码隐藏中,您需要三个处理程序;一个用于单元格,一个用于每种类型的控件(组合框、文本框):

    /// <summary>
    /// Skips the 'DataGridCell.Focus' step and goes straight into IsEditing
    /// </summary>
    private void DataGridCell_OnGotFocus(object sender, RoutedEventArgs e)
    
        DataGridCell cell = sender as DataGridCell;
        cell.IsEditing = true;
    

    /// <summary>
    /// Skips the 'IsEditing' step and goes straight into IsDropDownOpen
    /// </summary>
    private void Combobox_Loaded(object sender, RoutedEventArgs e)
    
        ComboBox comboBox = sender as ComboBox;
        comboBox.IsDropDownOpen = true;
    

    /// <summary>
    /// Skips the 'IsEditing' step and goes straight into Focus
    /// </summary>
    private void TextBox_Loaded(object sender, RoutedEventArgs e)
    
        TextBox textBox = sender as TextBox;
        textBox.Focus();
    

【讨论】:

以上是关于在 WPF 数据网格、组合框模板列上单击编辑的主要内容,如果未能解决你的问题,请参考以下文章

WPF如何在数据网格中填充组合框

WPF C# 组合框空白 SelectedItem SelectedValue

用于组合框模板的 WPF 高亮画笔

ExtJS 4 - 当列编辑器是组合框时如何避免网格列值变为空?

WPF - 根据项目模板更改组合框样式

网格面板中的 EXT.NET 组合框显示值而不是文本