简体   繁体   English

如何以编程方式在WPF DataGrid中选择行或单元格?

[英]How to select a row or a cell in WPF DataGrid programmatically?

In WinForm DataGridView, it automatically selects the first row when initialized. 在WinForm DataGridView中,它会在初始化时自动选择第一行。 It drove me crazy when I tried to turn that feature off. 当我试图关掉这个功能时,它让我抓狂。 Moving to WPF DataGrid, it seems Microsoft has decided to turn this feature off, which is a good thing I think. 转移到WPF DataGrid,似乎微软决定关闭这个功能,这是我认为的好事。 However, I have hard time to enable this feature now. 但是,我现在很难启用此功能。 For some DataGrid, I want the first row to be selected automatically after grid is populated through data binding. 对于某些DataGrid,我希望在通过数据绑定填充网格后自动选择第一行。 There are some suggestions in Internet, but I couldn't make that work. 互联网上有一些建议,但我无法做到这一点。 I hope for better luck here. 我希望在这里有更好的运气。

Set IsSynchronizedWithCurrentItem = "true" . 设置IsSynchronizedWithCurrentItem = "true"

EDIT: 编辑:

To address your comment, I assume that your DataGrid's SelectionUnit is set to "Cell", is it? 为了解决您的评论,我假设您的DataGrid的SelectionUnit设置为“Cell”,是吗? Okay, I'm not sure if this is the best solution but one thing you can do is handle the Loaded event for the DataGrid and manually set the selected cell in the code-behind. 好的,我不确定这是否是最好的解决方案,但您可以做的一件事是处理DataGrid的Loaded事件并在代码隐藏中手动设置选定的单元格。 So you'll have something like this: 所以你会有这样的事情:

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

Event-Handler: 事件处理程序:

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);
    }
}

Note that this will only work if the DataGrid.SelectionUnit is set to "Cell". 请注意,这仅在DataGrid.SelectionUnit设置为“Cell”时才有效。 Otherwise, I believe it will throw an exception. 否则,我相信会抛出异常。

EDIT2: EDIT2:

XAML: 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>

Code-Behind: 代码隐藏:

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();
        }
    }
}

You can do this consistently in the DataGrid.Loaded event. 您可以在DataGrid.Loaded事件中一致地执行此操作。 Just obtain the first row and have the row fire the selection event. 只需获取第一行并让行触发选择事件。

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

} 

I'm not sure this is a bug because you may not be guaranteed to have selection events fire from your object until the control is loaded. 我不确定这是一个错误,因为在加载控件之前,可能无法保证您的对象可以触发选择事件。 Don't know. 不知道。

You could try this. 你可以试试这个。

        this.dataGrid.SelectionMode = DataGridSelectionMode.Single;

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

I'm glad to report I found a solution for this problem through ItemContainerGenerator.StatusChanged event. 我很高兴通过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;
            }
        }

It looks when this event is fired with status ContainersGenerated, dataGrid is fully initialized. 它查看此事件以状态ContainersGenerated触发时,dataGrid已完全初始化。 To me, this is more like DataGridView's DataBindingComplete event in WinForm. 对我来说,这更像是WinForm中DataGridView的DataBindingComplete事件。 If so, the " DataContextChanged " event should really be called " DataContextChanging " event. 如果是这样,“ DataContextChanged ”事件应该被称为“ DataContextChanging ”事件。

This was inspired by a post here I accidently found while looking for another clue. 这是由一个帖子的启发在这里我无意中发现而寻找另一条线索。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM