Datagrid.SelectedItem
を使用してプログラムで行を選択するにはどうすればよいですか?
最初にIEnumerable
オブジェクトのDataGridRow
を作成し、このSelectedItem
プロパティに一致する行を渡す必要がありますか?
編集:
行を選択する前に、最初の列のセルの内容をTextBox.Text
と最初に一致させる必要があります。
以下のコードが機能するかどうかを確認してください。 datagrisの最初の列のセルを反復処理し、セルの内容が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
行を反復処理する必要はありません。よりシンプルなソリューションで目標を達成できます。行を一致させるために、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
を目的の値に設定することだけです。
このソリューションには長所と短所がありますが、特定のケースでは高速で簡単です。
宜しくお願いします
マルシン
あなたがやろうとしていることをやるのは私が好むよりも少し難しいですが、それはあなたがDataGrid
をDataTable
に直接バインドしていないからです。
_DataGrid.ItemsSource
_をDataTable
にバインドすると、実際にはテーブル自体ではなく、デフォルトのDataView
にバインドされます。これが、たとえば、列ヘッダーをクリックしたときにDataGrid
ソート行を作成するために何もする必要がない理由です-その機能はDataView
に焼き付けられており、DataGrid
は(IBindingList
インターフェイスを介して)アクセスする方法を知っています。
DataView
は_IEnumerable<DataRowView>
_(多かれ少なかれ)を実装し、DataGrid
はこれを反復してその項目を埋めます。つまり、_DataGrid.ItemsSource
_をDataTable
にバインドした場合、そのSelectedItem
プロパティはDataRowView
ではなくDataRow
になります。
これをすべて知っていれば、バインドできるプロパティを公開できるラッパークラスを構築するのは非常に簡単です。 3つの重要なプロパティがあります。
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;
}
}
ここでつまずいた人がOnSelectionChangedの後に発生する内部グリッド選択に問題がある場合-すべての選択セッターを数十時間試して失敗した後、私のために働いた唯一のことは、選択されたアイテムとともにDataGridをリロードして再設定することでした。まったくエレガントではありませんが、この時点で、私の状況にもっと良い解決策があるかどうかはわかりません。
datagrid.ItemsSource = null
datagrid.ItemsSource = items;
datagrid.SelectedItem = selectedItem;
このかなり最近の(質問の時代と比較して)TechNetの記事には、このトピックで見つけられる最高のテクニックがいくつか含まれています。
WPF:DataGridの行またはセルをプログラムで選択してフォーカスする
ほとんどの要件をカバーする詳細が含まれています。一部の行のDataGridRowにカスタムテンプレートを指定すると、これらの行にDataGridCellが含まれないため、グリッドの通常の選択メカニズムが機能しないことに注意してください。
他の人が述べたように、質問の最初の部分に答えるために、グリッドに与えたデータソースをより具体的にする必要があります。