如何使用 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 23:46:00  来源:igfitidea点击:

How to set selected item of a DataGrid programmatically in WPF with MVVM application?

wpfmvvmdatagriddatatable

提问by Haritha

I have bound the DataTableto the DataGridcontrol. How can I set the selected item programmatically?

我已将 绑定DataTableDataGrid控件。如何以编程方式设置所选项目?

Example

例子

In my view modelI 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 constructorof 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, sColumnand mColumnand added three rows namely row1, row2and row2.

好的。我创建了三列,即sizeQuantityColumnsColumnmColumn和添加三行即row1row2row2

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 SelectedIndexof the DataGrid to 1. (So the second row should be selected). In design timeit 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.

所以最终问题是不突出显示行。

enter image description here

在此处输入图片说明

回答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 SelectedIndexthis 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;

SelectedItemwill 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 SelectedValuewith SelectedValuePathset, in this case you set the column you want to select with and then to can select the row by setting the corresponding value

最常见的一种是SelectedValuewith SelectedValuePathset,在这种情况下你设置要选择的列,然后通过设置相应的值就可以选择行

<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:

结果:

enter image description here

在此处输入图片说明

回答by Erti-Chris Eelmaa

You can always use SelectedItemproperty and bind it against row, as such:

您始终可以使用SelectedItem属性并将其绑定到行,如下所示:

SelectedItem="{Binding ActiveRow}"

and in ViewModeldo:

并在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 Loadedevent 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 LoadDatamethod in the ViewModel:

在每种情况下,您都调用LoadDataViewModel 中的方法:

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集合。我发现设置SelectedIndexSelectedItem 会突出显示 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");               
        }                
    }