无法选择 WPF 数据网格中的第一行

本文关键字:一行 选择 WPF 数据 网格 数据网 | 更新日期: 2023-09-27 18:33:42

我有一个 WPF 数据网格,其中有 3 列作为窗口的一部分。ItemsSource 是从一组付款对象 (grdPayments.ItemsSource = payments ) 设置的。 当焦点设置为后面代码中的网格时,我希望第一行中的第三个单元格获得焦点。

无论我使用以下哪种方法,都会选择并聚焦第二行而不是第一行。

这会将焦点设置为第 2 行中的第 3 个单元格:

grdPayments.Focus();
grdPayments.CurrentCell = new DataGridCellInfo(grdPayments.Items[0],grdPayments.Columns[2]);
grdPayments.SelectedCells.Add(dataGridCellInfo);
cell.Focus();
grdPayments.BeginEdit();

这会将焦点设置为第二行:

grdPayments.Focus();
grdPayments.SelectedIndex  = 0;
grdPayments.BeginEdit();

谁能告诉我发生了什么? DataGrid XAML 如下所示。my:NumberEntry 是一个自定义控件:

<DataGrid Name="grdPayments"
          AutoGenerateColumns="False"
          Background="#FF21B721"
          ItemsSource="{Binding}"
          SelectionUnit="Cell"
          SelectionMode="Single"
          Margin="5"
          VirtualizingPanel.IsVirtualizing="False">
      <DataGrid.Resources>
          <Style TargetType="{x:Type DataGridColumnHeader}">
              <Setter Property="Background" Value="#FF21B721"/>
          </Style>
      </DataGrid.Resources>
      <DataGrid.Columns>
          <DataGridTextColumn Width="240"
                              Binding="{Binding Path=Description}"
                              Header="Description"
                              IsReadOnly="True"
                              TextBlock.TextAlignment="Center">
              <DataGridTextColumn.CellStyle>
                  <Style TargetType="DataGridCell">
                      <Setter Property="Background" Value="{StaticResource clBr}"/>
                  </Style>
              </DataGridTextColumn.CellStyle>
          </DataGridTextColumn>
          <DataGridTemplateColumn Width="100" Header="Due">
              <DataGridTemplateColumn.CellTemplate>
                  <DataTemplate>
                      <TextBlock Width="100" Text="{Binding Path=Due, Converter={StaticResource CurrencyPadder}, ConverterParameter=10}" Background="{StaticResource clBr}" Focusable="False"/>
                  </DataTemplate>
              </DataGridTemplateColumn.CellTemplate>
          </DataGridTemplateColumn>
          <DataGridTemplateColumn Width="100" Header="Paid">
              <DataGridTemplateColumn.CellStyle>
                  <Style TargetType="DataGridCell">
                      <Setter Property="Background" Value="{StaticResource clBr}"/>
                  </Style>
              </DataGridTemplateColumn.CellStyle>
              <DataGridTemplateColumn.CellTemplate>
                  <DataTemplate>
                      <my:NumberEntry Decimals="2"
                                      LostFocus="NumberEditor_LostFocus"
                               PreviewKeyDown="NumberEditor_PreviewKeyDown"
                                      MaxLength="10"
                                      TextAlignment="Right"
                                      Text="{Binding Path=Paid, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                  </DataTemplate>
              </DataGridTemplateColumn.CellTemplate>
          </DataGridTemplateColumn>
      </DataGrid.Columns>

无法选择 WPF 数据网格中的第一行

我 99% 确定您需要删除:

SelectionUnit="Cell"

要访问SelectionUnit设置为 Cell 的行,您必须执行以下操作:

grdPayments.SelectedItem = grdPayments.SelectedCells[0].item;

仅当您一次只能选择一个单元格(不在扩展模式下)时,它才有效。

使 WPF 数据网格按照我希望的方式运行似乎是一个失败的原因:它只是没有设计为根据我的需求运行。

相反,我所做的是在代码隐藏中动态构建一个单元格网格。 一行中的每个单元格都可以进行精细设计,以执行我想要的任何操作。

这是我的最终且成功的代码:

        Binding bind = null;
        for (int r = 1; r <= rows; r++)
        {
            bind = new Binding("Description");
            bind.Source = payments[r - 1];
            TextBlock col = new TextBlock();
            BindingOperations.SetBinding(col, TextBlock.TextProperty, bind);
            col.TextAlignment = TextAlignment.Left;
            col.VerticalAlignment = VerticalAlignment.Center;
            col.Width = 240;
            bdr = new Border();
            bdr.BorderBrush = System.Windows.Media.Brushes.Black;
            bdr.BorderThickness = new Thickness(2);
            Grid.SetColumn(bdr, 0);
            Grid.SetRow(bdr, r);
            bdr.Child = col;
            grdPayments.Children.Add(bdr);
            bind = new Binding("Due");
            bind.Source = payments[r - 1];
            bind.Converter = new MbcsCentral.CurrencyPaddingConverter();
            bind.ConverterParameter = "10";
            col = new TextBlock();
            BindingOperations.SetBinding(col, TextBlock.TextProperty, bind);
            col.TextAlignment = TextAlignment.Right;
            col.VerticalAlignment = VerticalAlignment.Center;
            col.HorizontalAlignment = HorizontalAlignment.Left;
            col.Width = 100;
            bdr = new Border();
            bdr.BorderBrush = System.Windows.Media.Brushes.Black;
            bdr.BorderThickness = new Thickness(2);
            Grid.SetColumn(bdr, 1);
            Grid.SetRow(bdr, r);
            bdr.Child = col;
            grdPayments.Children.Add(bdr);

            NumberEntry vi = new NumberEntry();
            bind = new Binding("Paid");
            bind.Source = payments[r - 1];
            bind.StringFormat = "######0.00";
            BindingOperations.SetBinding(vi, NumberEntry.TextProperty, bind);
            vi.MaxLength = 10;
            vi.Decimals = 2;
            vi.Width = 100;
            vi.LostFocus += NumberEditor_LostFocus;
            vi.PreviewKeyDown += PaidBlock_PreviewKeyDown;
            bdr = new Border();
            bdr.BorderBrush = System.Windows.Media.Brushes.Black;
            bdr.BorderThickness = new Thickness(2);
            Grid.SetColumn(bdr, 2);
            Grid.SetRow(bdr, r);
            bdr.Child = vi;
            grdPayments.Children.Add(bdr);
        }

grdPayments 现在是 XAML 中的一个空网格:一个占位符。 每个单元格都由一个包裹在边框中的 UiElement 组成,绑定到数据并设置到网格中的正确行/列中。

我不知道我是否会以这种方式处理比这里需要的更多的列,但这是一个简单且非常可行的解决方案,能够简单地将焦点设置在任何单元格后面的代码中,然后进入编辑模式无需单击。

不像 WPF 纯粹主义者可能更喜欢的声明性,但我在编程生涯的早期就了解到,最终重要的是它有效。