【问题标题】:How to select a row or a cell in WPF DataGrid programmatically?如何以编程方式在 WPF DataGrid 中选择一行或一个单元格?
【发布时间】:2010-10-01 02:36:50
【问题描述】:

在WinForm DataGridView中,初始化时会自动选择第一行。当我试图关闭该功能时,它让我发疯。转向 WPF DataGrid,微软似乎决定关闭此功能,我认为这是一件好事。但是,我现在很难启用此功能。对于某些 DataGrid,我希望在通过数据绑定填充网格后自动选择第一行。互联网上有一些建议,但我无法做到这一点。我希望在这里能有更好的运气。

【问题讨论】:

    标签: c# wpf select datagrid row


    【解决方案1】:

    设置IsSynchronizedWithCurrentItem = "true"

    编辑:

    为了解决您的评论,我假设您的 DataGrid 的 SelectionUnit 设置为“单元格”,是吗?好的,我不确定这是否是最佳解决方案,但您可以做的一件事是处理 DataGrid 的 Loaded 事件并在代码隐藏中手动设置选定的单元格。所以你会有这样的东西:

    <DataGrid x:Name="dg" AutoGenerateColumns="False" IsSynchronizedWithCurrentItem="True"
                SelectedCellsChanged="dg_SelectedCellsChanged" SelectionUnit="Cell"
                Loaded="dg_Loaded">
        ...
    </DataGrid>
    

    事件处理程序:

    private void dg_Loaded(object sender, RoutedEventArgs e)
    {
        if ((dg.Items.Count > 0) &&
            (dg.Columns.Count > 0))
        {
            //Select the first column of the first item.
            dg.CurrentCell = new DataGridCellInfo(dg.Items[0], dg.Columns[0]);
            dg.SelectedCells.Add(dg.CurrentCell);
        }
    }
    

    请注意,这仅在 DataGrid.SelectionUnit 设置为“单元格”时才有效。否则,我相信它会抛出异常。

    EDIT2:

    XAML:

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <StackPanel>
            <Button Click="Button_Click">Reset</Button>
            <DataGrid x:Name="dg" AutoGenerateColumns="False" IsSynchronizedWithCurrentItem="True"
                    SelectionUnit="Cell"
                    DataContextChanged="dg_DataContextChanged"
                    ItemsSource="{Binding Items}"
                    Loaded="dg_Loaded">
                <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding}"/>
                </DataGrid.Columns>
            </DataGrid>
        </StackPanel>
    </Window>
    

    代码隐藏:

    namespace WpfApplication1
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                this.LoadItems();
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                this.LoadItems();
            }
    
            private void LoadItems()
            {
                this.DataContext = new { Items = new List<string> { "Item1", "Item2", "Item3" } };
                this.SelectFirstItem();
            }
    
            private void dg_Loaded(object sender, RoutedEventArgs e)
            {
                SelectFirstItem();
            }
    
            void SelectFirstItem()
            {
                if ((dg.Items.Count > 0) &&
                    (dg.Columns.Count > 0))
                {
                    //Select the first column of the first item.
                    dg.CurrentCell = new DataGridCellInfo(dg.Items[0], dg.Columns[0]);
                    dg.SelectedCells.Add(dg.CurrentCell);
                }
            }
    
            private void dg_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
            {
                this.SelectFirstItem();
            }
        }
    }
    

    【讨论】:

    • 非常感谢您的提示。我刚试过。将其设置为 true 将使 DataGrid 的第一行“突出显示”,但未被选中。我需要触发 SelectedCellsChanged 事件。那么,如何让这个事件也被触发呢?
    • @karmicpuppet:此代码适用于 dg_Loaded 事件。但是,它确实在 DataContextChanged 事件中起作用。本质上,相同的网格被重复使用。每次设置数据数据上下文时,我都希望自动选择第一行,这应该触发 SelectedCellsChanged 事件,因为我依赖它。
    • @karmicpuppet 再次:我认为这与我的另一个问题有关: WPF DataGrid DataBindingComplete 事件在哪里?有人将我指向 DataContextChanged 事件。正如我所观察到的,DataContextChanged 事件实际上是在我设置新的数据上下文后触发的。但是,我无法使视觉效果在此事件处理程序中起作用。很奇怪。
    • 我认为 WPF 中没有 DataBindingComplete 事件。我不知道。试试“dataGrid.ItemContainerGenerator.ItemsChanged”事件怎么样?
    • @karmicpuppet:刚刚用 DataGrid.ItemContainerGenerator.ItemsChanged 事件尝试过,行为似乎与 DataContextChanged 相同。
    【解决方案2】:

    您可以在 DataGrid.Loaded 事件中始终如一地执行此操作。只需获取第一行并让该行触发选择事件。

    void MyGridLoaded(...) {
    DataGridRow r = yourGrid.ItemContainergenerator.ContainerFromIndex(0) as DataGridRow;
      if(r != null) {
         r.IsSelected = false;
         r.IsSelected = true;
      }
    
    } 
    

    我不确定这是一个错误,因为在加载控件之前,您可能无法保证从您的对象中触发选择事件。不知道。

    【讨论】:

      【解决方案3】:

      你可以试试这个。

              this.dataGrid.SelectionMode = DataGridSelectionMode.Single;
      
              // Selects the 4th row.
              this.dataGrid.SelectedIndex = 3;
      

      【讨论】:

      • 这是行选择的。
      • @Avatar:我刚刚尝试了你的建议。它似乎与 IsSynchronizedWithCurrentItem 具有相同的效果。因此,它只是突出显示该行,但我没有收到 SelectedCellsChanged 事件。不幸的是,没有“SelectedRowChanged”事件或类似事件。与 WinForm DataGridView 相比,WPF DataGrid 的事件很少。
      • @miliu SelectedCellsChanged 事件应该被触发不知道是什么问题。我这里有一个样本。请检查一下。这可能会给你一些想法。 filefactory.com/file/b3bhf1d/n/DataGridCheckBoxSelection.zip
      • @Avatar:我无法从 FileFactory 下载你的文件。它要求我注册以摆脱弹出广告。我做到了,但它仍然弹出。我必须等待 30 秒。我做到了,但是当我单击时,整个循环又开始了,它最终使我的 IE 崩溃。它崩溃了三遍。我讨厌那些有大量弹出窗口的网页。他们真的从中赚钱吗?
      • 不要做那些事情。我以为他们是免费的。好的,我已经在这里上传了文件sites.google.com/site/html5tutorials/… 我想这更安全
      【解决方案4】:

      我很高兴报告我通过ItemContainerGenerator.StatusChanged 事件找到了解决此问题的方法。

      dataGrid.ItemContainerGenerator.StatusChanged += new EventHandler(ItemContainerGenerator_StatusChanged);
      
      void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
              {
                  if (dataGrid.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
                  {
                      dataGrid.SelectedIndex = 0;
                  }
              }
      

      当此事件以状态 ContainersGenerated 触发时,dataGrid 已完全初始化。对我来说,这更像是 WinForm 中 DataGridView 的 DataBindingComplete 事件。如果是这样,“DataContextChanged”事件应该真正称为“DataContextChanging”事件。

      这是我在寻找另一个线索时偶然发现的一个帖子 here 的启发。

      【讨论】:

      • 实际上,我刚刚意识到 ItemContainerGenerator_StatusChanged 事件可能被触发太多次。我转回 DataContextChanged 事件并通过 Dispatcher.BeginInvoke 使其工作。
      猜你喜欢
      • 1970-01-01
      • 2021-03-15
      • 1970-01-01
      • 2012-10-23
      • 2016-05-28
      • 2011-04-22
      • 1970-01-01
      • 2017-01-26
      • 1970-01-01
      相关资源
      最近更新 更多