WPF Datagrid установил выбранную строку
Как использовать Datagrid.SelectedItem
для выбора строки программно?
Должен ли я сначала создать объект IEnumerable
из DataGridRow
и передать соответствующую строку этому свойству SelectedItem
или как это сделать?
EDIT:
Мне нужно сначала сопоставить содержимое ячейки первой ячейки столбца с TextBox.Text
, прежде чем выбирать строку.
Ответы
Ответ 1
пожалуйста, проверьте, работает ли код ниже для вас; он выполняет итерацию через ячейки первого столбца datagris и проверяет, соответствует ли содержимое ячейки текстовому значению и выбирает строку.
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;
}
}
надеюсь, что это поможет, считает
Ответ 2
Вам не нужно перебирать строки 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;
}
}
Ответ 3
Немного сложнее делать то, что вы пытаетесь сделать, чем мне хотелось бы, но это потому, что вы действительно не привязываете 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
, свойство string, которое при его установке найдет первое совпадение 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 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>
Ответ 4
Я искал решение подобной проблемы, и, возможно, мой способ поможет вам и любому, кто сталкивается с этим.
Я использовал SelectedValuePath="id"
в определении XAML DataGrid, и программным образом мне нужно только установить DataGrid.SelectedValue
в нужное значение.
Я знаю, что это решение имеет свои плюсы и минусы, но в конкретном случае это быстро и легко.
С наилучшими пожеланиями
Марцин
Ответ 5
//В общем для доступа ко всем строкам //
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);
}
}
Ответ 6
Я изменил код 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;
}
}
Ответ 7
Я столкнулся с этим довольно недавним (по сравнению с возрастом вопроса) статьей TechNet, которая включает некоторые из лучших техник, которые я мог найти по теме:
WPF: программный выбор и фокусировка строки или ячейки в DataGrid
Он содержит сведения, которые должны охватывать большинство требований. Важно помнить, что если вы укажете настраиваемые шаблоны для DataGridRow для некоторых строк, они не будут иметь DataGridCells внутри, а затем нормальные механизмы выбора сетки не будут работать.
Вам нужно будет уточнить, какой источник данных вы дали сетке, чтобы ответить на первую часть вашего вопроса, как заявили другие.
Ответ 8
Если у кого-то возникает проблема с выбором внутренней сетки после OnSelectionChanged - после безуспешного опробования всех наборов выбора в течение дюжины часов единственное, что сработало для меня, это перезагрузка и повторное заполнение DataGrid вместе с выбранным элементом. Не совсем элегантный, но на данный момент я не уверен, что в моей ситуации существует лучшее решение.
datagrid.ItemsSource = null
datagrid.ItemsSource = items;
datagrid.SelectedItem = selectedItem;