如何使用Datagrid.SelectedItem
在程序中自动选择一行?
我首先需要创建一个DataGridRow
对象的IEnumerable
,然后将匹配的行传递给此SelectedItem
属性吗?还是有其他方法呢?
编辑:
在选择行之前,我需要先匹配第一列单元格的单元格内容与TextBox.Text
。
如何使用Datagrid.SelectedItem
在程序中自动选择一行?
我首先需要创建一个DataGridRow
对象的IEnumerable
,然后将匹配的行传递给此SelectedItem
属性吗?还是有其他方法呢?
编辑:
在选择行之前,我需要先匹配第一列单元格的单元格内容与TextBox.Text
。
我的代码遍历datagrid
的第一列单元格,检查单元格内容是否等于textbox.text
的值,并选择该行。
for (int i = 0; i < dataGrid.Items.Count; i++)
{
DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(i);
TextBlock cellContent = dataGrid.Columns[0].GetCellContent(row) as TextBlock;
if (cellContent != null && cellContent.Text.Equals(textBox1.Text))
{
object item = dataGrid.Items[i];
dataGrid.SelectedItem = item;
dataGrid.ScrollIntoView(item);
row.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
break;
}
}
dataGrid.ScrollIntoView()
之前添加dataGrid.UpdateLayout()
非常有用-正如MSDN所指出的那样:当ItemsSource集合的内容发生变化时,特别是如果向集合中添加或删除了许多项,你可能需要在调用ScrollIntoView来滚动指定项到视口之前调用UpdateLayout。 - jwaliszkoDataGrid.Items.Count
远远超过 1000,但 ContainerFromIndex(i)
在前 7 个元素之后开始返回 null
。或者我漏掉了什么吗? - Boern您不需要遍历 DataGrid
的行,可以使用更简单的解决方案实现您的目标。
为了匹配您的行,您可以通过遍历绑定到 DataGrid.ItemsSource
属性的集合,然后在程序中将此项分配给您的 DataGrid.SelectedItem
属性,或者如果要允许用户选择多行,则可以将其添加到 DataGrid.SelectedItems
集合中。请参见下面的代码:
<Window x:Class="ProgGridSelection.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" Loaded="OnWindowLoaded">
<StackPanel>
<DataGrid Name="empDataGrid" ItemsSource="{Binding}" Height="200"/>
<TextBox Name="empNameTextBox"/>
<Button Content="Click" Click="OnSelectionButtonClick" />
</StackPanel>
public partial class MainWindow : Window
{
public class Employee
{
public string Code { get; set; }
public string Name { get; set; }
}
private ObservableCollection<Employee> _empCollection;
public MainWindow()
{
InitializeComponent();
}
private void OnWindowLoaded(object sender, RoutedEventArgs e)
{
// Generate test data
_empCollection =
new ObservableCollection<Employee>
{
new Employee {Code = "E001", Name = "Mohammed A. Fadil"},
new Employee {Code = "E013", Name = "Ahmed Yousif"},
new Employee {Code = "E431", Name = "Jasmin Kamal"},
};
/* Set the Window.DataContext, alternatively you can set your
* DataGrid DataContext property to the employees collection.
* on the other hand, you you have to bind your DataGrid
* DataContext property to the DataContext (see the XAML code)
*/
DataContext = _empCollection;
}
private void OnSelectionButtonClick(object sender, RoutedEventArgs e)
{
/* select the employee that his name matches the
* name on the TextBox
*/
var emp = (from i in _empCollection
where i.Name == empNameTextBox.Text.Trim()
select i).FirstOrDefault();
/* Now, to set the selected item on the DataGrid you just need
* assign the matched employee to your DataGrid SeletedItem
* property, alternatively you can add it to your DataGrid
* SelectedItems collection if you want to allow the user
* to select more than one row, e.g.:
* empDataGrid.SelectedItems.Add(emp);
*/
if (emp != null)
empDataGrid.SelectedItem = emp;
}
}
我曾经搜索过类似问题的解决方案,也许我的方法可以帮助您和任何遇到这个问题的人。
我在XAML DataGrid定义中使用了SelectedValuePath="id"
,并且编程时我只需要将DataGrid.SelectedValue
设置为所需的值。
我知道这种解决方案有利有弊,但在特定情况下,它是快速且简单的。
最好的问候
Marcin
DataGrid
绑定到 DataTable
。当你将 DataGrid.ItemsSource
绑定到 DataTable
时,实际上是将它绑定到默认的 DataView
,而不是表本身。这就是为什么,例如,当你单击列标题时,DataGrid
不需要进行任何操作即可对行进行排序 - 因为该功能已经集成在 DataView
中,并且 DataGrid
知道如何通过 IBindingList
接口访问它。
DataView
实现了 IEnumerable<DataRowView>
(或多或少),而 DataGrid
通过迭代来填充其项。这意味着当你将 DataGrid.ItemsSource
绑定到 DataTable
时,其 SelectedItem
属性将是一个 DataRowView
,而不是一个 DataRow
。Table
,即 DataTable
,
- Row
,一个双向可绑定的类型为 DataRowView
的属性,以及
- SearchText
,一个字符串属性,当设置它时,将在表的默认视图中查找第一个匹配的 DataRowView
,设置 Row
属性,并引发 PropertyChanged
。public class DataTableWrapper : INotifyPropertyChanged
{
private DataRowView _Row;
private string _SearchText;
public DataTableWrapper()
{
// using a parameterless constructor lets you create it directly in XAML
DataTable t = new DataTable();
t.Columns.Add("id", typeof (int));
t.Columns.Add("text", typeof (string));
// let's acquire some sample data
t.Rows.Add(new object[] { 1, "Tower"});
t.Rows.Add(new object[] { 2, "Luxor" });
t.Rows.Add(new object[] { 3, "American" });
t.Rows.Add(new object[] { 4, "Festival" });
t.Rows.Add(new object[] { 5, "Worldwide" });
t.Rows.Add(new object[] { 6, "Continental" });
t.Rows.Add(new object[] { 7, "Imperial" });
Table = t;
}
// you should have this defined as a code snippet if you work with WPF
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler h = PropertyChanged;
if (h != null)
{
h(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
// SelectedItem gets bound to this two-way
public DataRowView Row
{
get { return _Row; }
set
{
if (_Row != value)
{
_Row = value;
OnPropertyChanged("Row");
}
}
}
// the search TextBox is bound two-way to this
public string SearchText
{
get { return _SearchText; }
set
{
if (_SearchText != value)
{
_SearchText = value;
Row = Table.DefaultView.OfType<DataRowView>()
.Where(x => x.Row.Field<string>("text").Contains(_SearchText))
.FirstOrDefault();
}
}
}
public DataTable Table { get; private set; }
}
以下是使用它的XAML代码:
<Window x:Class="DataGridSelectionDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
xmlns:DataGridSelectionDemo="clr-namespace:DataGridSelectionDemo"
Title="DataGrid selection demo"
Height="350"
Width="525">
<Window.DataContext>
<DataGridSelectionDemo:DataTableWrapper />
</Window.DataContext>
<DockPanel>
<Grid DockPanel.Dock="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label>Text</Label>
<TextBox Grid.Column="1"
Text="{Binding SearchText, Mode=TwoWay}" />
</Grid>
<dg:DataGrid DockPanel.Dock="Top"
ItemsSource="{Binding Table}"
SelectedItem="{Binding Row, Mode=TwoWay}" />
</DockPanel>
</Window>
// 一般情况下访问所有行 //
foreach (var item in dataGrid1.Items)
{
string str = ((DataRowView)dataGrid1.Items[1]).Row["ColumnName"].ToString();
}
//访问选定的行 //
private void dataGrid1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
string str = ((DataRowView)dataGrid1.SelectedItem).Row["ColumnName"].ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
我修改了serge_gubenko的代码,现在它运行得更好了
for (int i = 0; i < dataGrid.Items.Count; i++)
{
string txt = searchTxt.Text;
dataGrid.ScrollIntoView(dataGrid.Items[i]);
DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(i);
TextBlock cellContent = dataGrid.Columns[1].GetCellContent(row) as TextBlock;
if (cellContent != null && cellContent.Text.ToLower().Equals(txt.ToLower()))
{
object item = dataGrid.Items[i];
dataGrid.SelectedItem = item;
dataGrid.ScrollIntoView(item);
row.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
break;
}
}
WPF: Programmatically Selecting and Focusing a Row or Cell in a DataGrid
它包含了应该覆盖大多数要求的详细信息。重要的是要记住,如果为某些行指定了DataGridRow的自定义模板,则这些行将没有DataGridCells,然后网格的正常选择机制将无法工作。
您需要更具体地说明您已经为网格提供了什么数据源,以回答您问题的第一部分,就像其他人所说的那样。
datagrid.ItemsSource = null
datagrid.ItemsSource = items;
datagrid.SelectedItem = selectedItem;