【问题标题】:Unable to select first row in WPF DataGrid无法选择 WPF DataGrid 中的第一行
【发布时间】:2016-02-09 02:08:01
【问题描述】:

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

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

这会将焦点设置到第二行的第三个单元格:

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>

【问题讨论】:

  • 明确地说,我想在第一行中选择一个单元格,但只能选择整个第二行或第二行中的一个单元格。我已经尝试了我在网上找到的所有解决方案,但都无济于事。一定有办法!
  • 好的。如果 SelectionUnit=Fullrow 和 SelectionMode=Extended,则选择第一行。我还需要做两件事:1)选择一个单元格。 2) 以编程方式将该单元格置于编辑模式。令人沮丧的是,DataGrid 的 WPF 版本让如此明显需要的功能变得如此困难。

标签: c# wpf xaml datagrid


【解决方案1】:

我 99% 确定您需要删除:

SelectionUnit="Cell"

【讨论】:

  • 只有在 100% 确定的情况下才应该发布答案,否则,只需发表评论 :)
  • 除非那个单元格是我真正想要被选中的。
【解决方案2】:

要访问SelectionUnit 设置为Cell 的行,您必须这样做:

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

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

【讨论】:

    【解决方案3】:

    让 WPF DataGrid 以我希望的方式运行似乎是一个失败的原因:它根本不是按照我的需要设计的。

    我所做的是在后面的代码中动态构建单元格网格。一行中的每个单元格都可以被精心设计为做任何我想做的事情。

    这是我的最终成功代码:

            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 组成,绑定到数据并设置到 Grid 中的正确行/列中。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-12
      • 1970-01-01
      • 1970-01-01
      • 2012-06-27
      相关资源
      最近更新 更多