Это немного сложнее делать то, что вы пытаетесь сделать, чем я предпочел бы, но это потому, что вы на самом деле не напрямую связать DataGrid
с DataTable
.
Когда вы связываете DataGrid.ItemsSource
с номером DataTable
, вы действительно привязываете его к умолчанию DataView
, а не к самой таблице. Вот почему, например, вам не нужно ничего делать, чтобы сделать строки сортировки DataGrid
, когда вы нажимаете на заголовок столбца - эта функция испечена в DataView
, а DataGrid
знает, как получить к ней доступ (через интерфейс IBindingList
).
DataView
инвентарь IEnumerable<DataRowView>
(более или менее), а DataGrid
заполняет свои изделия, итерируя по этому вопросу. Это означает, что когда вы связали DataGrid.ItemsSource
с DataTable
, его SelectedItem
будет DataRowView
, а не DataRow
.
Если вы знаете все это, довольно просто создать класс-оболочку, который позволяет вам открывать свойства, к которым вы можете привязать. Есть три основных свойства:
Table
, то DataTable
,
- , двухсторонняя Привязываемое свойство типа
DataRowView
и
SearchText
, струнный свойство, которое, когда оно установлено, найдет сначала сопоставьте DataRowView
в представлении таблицы по умолчанию, установите свойство и поднимите 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>
Вы используете WPF Toolkit DataGrid? – jsmith
@jsmith Да, это тот, который я использую. –