如何使用 MVVM 应用程序在 WPF 中以编程方式设置 DataGrid 的选定项目?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15826142/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set selected item of a DataGrid programmatically in WPF with MVVM application?
提问by Haritha
I have bound the DataTable
to the DataGrid
control. How can I set the selected item programmatically?
我已将 绑定DataTable
到DataGrid
控件。如何以编程方式设置所选项目?
Example
例子
In my view model
I have a property of type DataTable to bind the DataGrid
在我的view model
我有一个 DataTable 类型的属性来绑定 DataGrid
private DataTable sizeQuantityTable;
public DataTable SizeQuantityTable
{
get
{
return sizeQuantityTable;
}
set
{
sizeQuantityTable = value;
NotifyPropertyChanged("SizeQuantityTable");
}
}
My XAML
我的 XAML
<DataGrid
ItemsSource="{Binding SizeQuantityTable}"
AutoGenerateColumns="True"
Margin="0,0,0,120" />
The constructor
of the view model (assigning dummy values)
该constructor
视图模型的(分配虚拟值)
this.SizeQuantityTable = new DataTable();
DataColumn sizeQuantityColumn = new DataColumn();
sizeQuantityColumn.ColumnName = "Size Quantity";
this.SizeQuantityTable.Columns.Add(sizeQuantityColumn);
DataColumn sColumn = new DataColumn();
sColumn.ColumnName = "S";
this.SizeQuantityTable.Columns.Add(sColumn);
DataColumn mColumn = new DataColumn();
mColumn.ColumnName = "M";
this.SizeQuantityTable.Columns.Add(mColumn);
DataRow row1 = this.SizeQuantityTable.NewRow();
row1[sizeQuantityColumn] = "Blue";
row1[sColumn] = "12";
row1[mColumn] = "15";
this.SizeQuantityTable.Rows.Add(row1);
DataRow row2 = this.SizeQuantityTable.NewRow();
row2[sizeQuantityColumn] = "Red";
row2[sColumn] = "18";
row2[mColumn] = "21";
this.SizeQuantityTable.Rows.Add(row2);
DataRow row3 = this.SizeQuantityTable.NewRow();
row3[sizeQuantityColumn] = "Green";
row3[sColumn] = "24";
row3[mColumn] = "27";
this.SizeQuantityTable.Rows.Add(row3);
OK. I have created three columns namely sizeQuantityColumn
, sColumn
and mColumn
and added three rows namely row1
, row2
and row2
.
好的。我创建了三列,即sizeQuantityColumn
,sColumn
与mColumn
和添加三行即row1
,row2
和row2
。
So, Let's say I wanna set the selected item as row2
(So in the view, the second row should be highlighted).
所以,假设我想将所选项目设置为row2
(所以在视图中,第二行应该突出显示)。
How can I do this?
我怎样才能做到这一点?
EDIT
编辑
I hardcoded the SelectedIndex
of the DataGrid to 1. (So the second row should be selected). In design time
it shows as selected. But not in the run time. You can see it in the below snapshot.
我SelectedIndex
将 DataGrid 的硬编码为 1。(因此应选择第二行)。在design time
它显示为选中。但不是在运行时。您可以在下面的快照中看到它。
So ultimaltely the problem is Not highlightingthe row.
所以最终问题是不突出显示行。
回答by sa_ddam213
There are a few way to select items in the DataGrid
. It just depends which one works best for the situation
有几种方法可以在DataGrid
. 这只是取决于哪种情况最适合这种情况
First and most basic is SelectedIndex
this will just select the Row at that index in the DataGrid
首先也是最基本的是SelectedIndex
这将只选择该索引处的行DataGrid
<DataGrid SelectedIndex="{Binding SelectedIndex}" />
private int _selectedIndex;
public int SelectedIndex
{
get { return _selectedIndex; }
set { _selectedIndex = value; NotifyPropertyChanged("SelectedIndex"); }
}
SelectedIndex = 2;
SelectedItem
will select the row that matches the row you set
SelectedItem
将选择与您设置的行匹配的行
<DataGrid SelectedItem="{Binding SelectedRow}" />
private DataRow _selectedRow;
public DataRow SelectedRow
{
get { return _selectedRow; }
set { _selectedRow = value; NotifyPropertyChanged("SelectedRow");}
}
SelectedRow = items.First(x => x.whatever == something);
The most common one is SelectedValue
with SelectedValuePath
set, in this case you set the column you want to select with and then to can select the row by setting the corresponding value
最常见的一种是SelectedValue
with SelectedValuePath
set,在这种情况下你设置要选择的列,然后通过设置相应的值就可以选择行
<DataGrid SelectedValuePath="Size Quantity" SelectedValue="{Binding SelectionValue}"
private string _selectedValue
public string SelectionValue
{
get { return _selectedValue; }
set { _selectedValue = value; NotifyPropertyChanged("SelectionValue"); }
}
SelectionValue = "Blue";
Edit:
编辑:
Here is my test and it is highlighting just fine
这是我的测试,它突出显示就好了
Code:
代码:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
this.SizeQuantityTable = new DataTable();
DataColumn sizeQuantityColumn = new DataColumn();
sizeQuantityColumn.ColumnName = "Size Quantity";
...................
........
}
private string _selectedValue;
public string SelectionValue
{
get { return _selectedValue; }
set { _selectedValue = value; NotifyPropertyChanged("SelectionValue"); }
}
private int _selectedIndex;
public int SelectedIndex
{
get { return _selectedIndex; }
set { _selectedIndex = value; NotifyPropertyChanged("SelectedIndex"); }
}
private DataTable sizeQuantityTable;
public DataTable SizeQuantityTable
{
get { return sizeQuantityTable; }
set { sizeQuantityTable = value; NotifyPropertyChanged("SizeQuantityTable"); }
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
SelectedIndex = 2;
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
SelectionValue = "Blue";
}
private void NotifyPropertyChanged(string p)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(p));
}
}
}
Xaml:
Xml:
<Window x:Class="WpfApplication21.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="202" Width="232" Name="UI">
<Grid DataContext="{Binding ElementName=UI}">
<DataGrid SelectedValuePath="Size Quantity"
SelectedValue="{Binding SelectionValue}"
SelectedIndex="{Binding SelectedIndex}"
ItemsSource="{Binding SizeQuantityTable}"
AutoGenerateColumns="True"
Margin="0,0,0,41" />
<StackPanel Orientation="Horizontal" Height="37" VerticalAlignment="Bottom" >
<Button Content="SelectedIndex" Height="26" Width="107" Click="Button_Click_1"/>
<Button Content="SelectedValue" Height="26" Width="107" Click="Button_Click_2"/>
</StackPanel>
</Grid>
</Window>
Result:
结果:
回答by Erti-Chris Eelmaa
You can always use SelectedItem
property and bind it against row, as such:
您始终可以使用SelectedItem
属性并将其绑定到行,如下所示:
SelectedItem="{Binding ActiveRow}"
and in ViewModel
do:
并在ViewModel
做:
ActiveRow = secondRow;
回答by fhnaseer
Add SelectedItem, SelectedValue in your DataGrid.
在 DataGrid 中添加 SelectedItem、SelectedValue。
<DataGrid
ItemsSource="{Binding SizeQuantityTable}"
AutoGenerateColumns="True"
SelectedValue ="{Binding SelectedValue}"
Margin="0,0,0,120" />
And in your view model
在你的视图模型中
private string _selectedValue;
public string SelectedValue
{
get
{
return _selectedValue;
}
set
{
_selectedValue = value;
NotifyPropertyChanged("SelectedValue");
}
}
private DataTable sizeQuantityTable;
public DataTable SizeQuantityTable
{
get
{
return sizeQuantityTable;
}
set
{
sizeQuantityTable = value;
NotifyPropertyChanged("SizeQuantityTable");
}
}
You can use SelectedItem as well, that is preferred.
您也可以使用 SelectedItem,这是首选。
回答by Martin
I just had the same problem. I saw that the item of a datagrid was selected correctly at design time, but not at runtime. (By the way, I create the instance of the view model in the xaml).
我只是遇到了同样的问题。我看到在设计时正确选择了数据网格的项目,但在运行时没有正确选择。(顺便说一下,我在 xaml 中创建了视图模型的实例)。
I could solve this problem by moving the code to programmatically set the selected item from the view models constructor to a different method in the view model and then calling this method in the loaded event of the window (or usercontrol).
我可以通过移动代码以编程方式将视图模型构造函数中的选定项设置为视图模型中的不同方法,然后在窗口(或用户控件)的加载事件中调用此方法来解决此问题。
Obviously the view is not completely done initializing itself when the view models constructor is called. This can be avoided by not coding in the view models constructor.
显然,当调用视图模型构造函数时,视图并没有完全完成初始化。这可以通过不在视图模型构造函数中编码来避免。
View (xaml):
查看(xml):
<Window x:Class="MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test"
xmlns:viewModel="clr-namespace:ViewModels" Loaded="Window_Loaded">
<Window.DataContext>
<viewModel:ExampleViewModel/>
</Window.DataContext>
View (code behind):
查看(代码隐藏):
private void Window_Loaded(object sender, RoutedEventArgs e)
{
((ExampleViewModel)this.DataContext).LoadData();
}
If you do not like setting up the Loaded
event in the code behind, you can also do it in xaml (references to "Microsoft.Expression.Interactions" and "System.Windows.Interactivity" are needed):
如果您不喜欢Loaded
在后面的代码中设置事件,也可以在 xaml 中进行(需要引用“Microsoft.Expression.Interactions”和“System.Windows.Interactivity”):
<Window x:Class="MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test"
xmlns:viewModel="clr-namespace:ViewModels">
<Window.DataContext>
<viewModel:ExampleViewModel/>
</Window.DataContext>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="LoadData"/>
</i:EventTrigger>
</i:Interaction.Triggers>
In each case, you call the LoadData
method in the ViewModel:
在每种情况下,您都调用LoadData
ViewModel 中的方法:
public class ExampleViewModel
{
/// <summary>
/// Constructor.
/// </summary>
public ExampleViewModel()
{
// Do NOT set selected item here
}
public void LoadData()
{
// Set selected item here
}
回答by DANGLES
For anyone using Observable Collections you may find this solution useful.
对于使用 Observable Collections 的任何人,您可能会发现此解决方案很有用。
The SelectedModelIndexproperty simply returns the index of the SelectedModelfrom the ItemSourcecollection. I've found setting the SelectedIndexalong with the SelectedItemhighlights the row in the DataGrid.
该SelectedModelIndex属性只是返回的索引SelectedModel从的ItemSource集合。我发现设置SelectedIndex和SelectedItem 会突出显示 DataGrid 中的行。
private ObservableCollection<Model> _itemSource
public ObservableCollection<Model> ItemSource
{
get { return _itemSource; }
set
{
_itemSource = value;
OnPropertyChanged("ItemSource");
}
}
// Binding must be set to One-Way for read-only properties
public int SelectedModelIndex
{
get
{
if (ItemSource != null && ItemSource.Count > 0)
return ItemSource.IndexOf(SelectedModel);
else
return -1;
}
}
private Model _selectedModel;
public Model SelectedModel
{
get { return _selectedModel; }
set
{
_selectedModel = value;
OnPropertyChanged("SelectedModel");
OnPropertyChanged("SelectedModelIndex");
}
}