按Enter键时移动到下一行而不提交行

时间:2016-09-07 10:39:56

标签: wpf xaml datagrid

我有一个包含数据的xaml数据网格,我使用的是mvvm。 我编辑后,我希望我的细胞能够改变颜色。我不关心保存颜色以供以后使用,我只想在编辑单元格内容后立即进行视觉更改。

我能够通过使用一些代码来实现上述行为(我想避免代码落后,但由于它纯粹是视觉,我猜它完全没问题):

  DesiredCapabilities dc=new DesiredCapabilities();    
  dc.setCapability("screen-resolution","1280x1024");

只要所选行具有焦点,这就可以正常工作。换句话说,我可以在同一行上来回切换,编辑的单元格具有指定的背景颜色。

现在,问题在于当我按下回车键时,该行似乎已提交,光标移动到下一行,编辑过的单元格的背景将返回其原始颜色。

为了完整性,这里是datagrid(减去几列):

private void MyGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    FrameworkElement element = e.Column.GetCellContent(MyGrid.SelectedItem);
    (element.Parent as DataGridCell).Background = (SolidColorBrush)Application.Current.Resources["EditedCellBackground"];
}

以下是datagrid的样式:

<DataGrid Style="{StaticResource MainContentDataGridTheme}"
                  ItemsSource="{Binding Source={StaticResource Categories}}"
                  Grid.Row="1"
                  x:Name="MyGrid"
                  CellEditEnding="MyGrid_CellEditEnding">
    <DataGrid.GroupStyle>
        <GroupStyle>
            <GroupStyle.Panel>
                <ItemsPanelTemplate>
                    <DataGridRowsPresenter/>
                </ItemsPanelTemplate>
            </GroupStyle.Panel>
            <GroupStyle.ContainerStyle>
                <Style TargetType="{x:Type GroupItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type GroupItem}">
                                <Expander Name="expander" IsExpanded="True">
                                    <Expander.Header>
                                        <StackPanel>
                                            <TextBlock Text="{Binding Name}"  FontWeight="DemiBold" FontSize="13" />
                                            <TextBlock Text="{Binding ItemCount, StringFormat={}Items: {0}}" FontSize="9" />
                                        </StackPanel>
                                    </Expander.Header>
                                    <ItemsPresenter />
                                </Expander>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.ContainerStyle>
        </GroupStyle>
    </DataGrid.GroupStyle>
    <DataGrid.ColumnHeaderStyle>
        <Style TargetType="DataGridColumnHeader">
            <Setter Property="HorizontalContentAlignment" Value="Right" />
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <TextBlock TextWrapping="WrapWithOverflow" TextTrimming="CharacterEllipsis" Text="{Binding}"></TextBlock>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGrid.ColumnHeaderStyle>
    <DataGrid.Columns>
        <DataGridTextColumn Width="25*" Binding="{Binding AppliedPercentage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                            Header="Applied %">
            <DataGridTextColumn.CellStyle>
                <Style>
                    <Setter Property="UIElement.IsEnabled" Value="{Binding IsEnabled}" />
                    <Setter Property="TextBlock.TextAlignment" Value="Right" />
                </Style>
            </DataGridTextColumn.CellStyle>
    </DataGrid.Columns>
</DataGrid>

如何在保持enter键行为的同时保留已编辑单元格的背景?我不介意丢失行提交(UpdateSourceTrigger负责更新我的属性),但我绝对想保持enter键的行为,也就是说:转到立即单元格下一行(下一行,同一列) ),并且可以立即编辑内容。

由于

1 个答案:

答案 0 :(得分:1)

经过一些研究,并尝试各种各样的事情,我终于找到了一个符合我要求的解决方法。

我添加了更多代码来执行以下操作:

  • 禁用行提交以防止已编辑单元格的背景重置为其原始颜色。
  • 抓住KeyUp事件以人为地重新创建回车键的行为。

因此,在xaml中,我将以下两个属性添加到我的数据网格中:

RowEditEnding="MyGrid_RowEditEnding"
KeyUp="MyGrid_KeyUp"

在后面的代码中,我实现了相应的方法:

private void MyGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
    // Prevents the row to be committed, but disable the "go to next row" behaviour 
    e.Cancel = true;
}

private void MyGrid_KeyUp(object sender, KeyEventArgs e)
{
    var uiElement = e.OriginalSource as UIElement;
    if (e.Key == Key.Enter && uiElement != null)
    {
        // Handle the key press as normal (-> validate the input)
            e.Handled = true;
            // Get the next element in the UI
            var nextUIElement = uiElement.PredictFocus(FocusNavigationDirection.Down);
            // Check if there if the next element is not null. This would occur with the last row of the grid.
            if (nextUIElement != null)
            {
                // Check if the element is a cell, rather than something else like an expander for instance...
                if (nextUIElement.GetType().Equals(typeof(DataGridCell)))
                {
                    DataGridCellInfo nextCellInfo = new DataGridCellInfo((DataGridCell)nextUIElement);
                    // Set the selected row
                    PrelimsGrid.SelectedItem = nextCellInfo.Item;
                    // Set the selected cell.
                    PrelimsGrid.CurrentCell = nextCellInfo;
                }
                else
                {
                    PrelimsGrid.SelectedItem = uiElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down));
                }
            }
        }
    }
}

虽然这对我有用,但我会谦虚地承认我不是一个非常有经验的开发人员,而且我很乐意阅读任何改进或替代解决方案。