8

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

例子

在我的view model我有一个 DataTable 类型的属性来绑定 DataGrid

 private DataTable sizeQuantityTable;

 public DataTable SizeQuantityTable
 {
        get
        {
            return sizeQuantityTable;
        }
        set
        {
            sizeQuantityTable = value;
            NotifyPropertyChanged("SizeQuantityTable");
        }
  }

我的XAML

<DataGrid 
            ItemsSource="{Binding SizeQuantityTable}"
            AutoGenerateColumns="True" 
            Margin="0,0,0,120" />

视图模型的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);

好的。我创建了三列sizeQuantityColumn,并添加了三行,即,sColumn和。mColumnrow1row2row2

所以,假设我想将选定的项目设置为row2(所以在视图中,第二行应该突出显示)。

我怎样才能做到这一点?

编辑

SelectedIndex将 DataGrid 的硬编码为 1。(所以应该选择第二行)。在design time它显示为选中。但不是在运行时。您可以在下面的快照中看到它。

所以最终的问题是没有突出显示该行。

在此处输入图像描述

4

6 回答 6

10

有几种方法可以选择DataGrid. 这取决于哪一个最适合这种情况

首先也是最基本的是,SelectedIndex这将只选择该索引处的行DataGrid

 <DataGrid SelectedIndex="{Binding SelectedIndex}" />

private int _selectedIndex;
public int SelectedIndex
{
    get { return _selectedIndex; }
    set { _selectedIndex = value; NotifyPropertyChanged("SelectedIndex"); }
}

SelectedIndex = 2;

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);

最常见的是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";

编辑:

这是我的测试,它突出显示就好了

代码:

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));
        }
    }
}

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>

结果:

在此处输入图像描述

于 2013-04-05T05:54:27.660 回答
3

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

SelectedItem="{Binding ActiveRow}"

并在ViewModel做:

ActiveRow = secondRow;
于 2013-04-05T05:48:29.423 回答
1

在 DataGrid 中添加 SelectedItem、SelectedValue。

<DataGrid 
        ItemsSource="{Binding SizeQuantityTable}"
        AutoGenerateColumns="True" 
        SelectedValue ="{Binding SelectedValue}"
        Margin="0,0,0,120" />

在你的视图模型中

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");
    }
}

您也可以使用 SelectedItem,这是首选。

于 2013-04-05T07:07:30.590 回答
1

我只是有同样的问题。我看到在设计时正确选择了数据网格的项目,但在运行时没有。(顺便说一句,我在 xaml 中创建了视图模型的实例)。

我可以通过移动代码以编程方式将所选项目从视图模型构造函数设置为视图模型中的不同方法,然后在窗口(或用户控件)的加载事件中调用此方法来解决此问题。

显然,当调用视图模型构造函数时,视图本身并没有完全完成初始化。这可以通过不在视图模型构造函数中编码来避免。

查看(xaml):

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

查看(后面的代码):

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        ((ExampleViewModel)this.DataContext).LoadData();
    }

如果您不喜欢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>

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

public class ExampleViewModel
{
    /// <summary>
    /// Constructor.
    /// </summary>
    public ExampleViewModel()
    {
        // Do NOT set selected item here
    }


    public void LoadData()
    {
        // Set selected item here
    }
于 2015-07-23T09:48:11.800 回答
0

对于使用 Observable Collections 的任何人,您可能会发现此解决方案很有用。

SelectedModelIndex属性只返回ItemSource集合中SelectedModel的索引。我发现设置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");               
        }                
    }
于 2015-10-29T08:04:39.843 回答
0

xml:

<DataGrid  SelectionUnit="FullRow" >
</DataGrid>

代码

SelectRowByIndex(yourDataGridViewName, 0);

public static void SelectRowByIndex(DataGrid dataGrid, int rowIndex)
        {
            if (!dataGrid.SelectionUnit.Equals(DataGridSelectionUnit.FullRow))
                throw new ArgumentException("The SelectionUnit of the DataGrid must be set to FullRow.");

            if (rowIndex < 0 || rowIndex > (dataGrid.Items.Count - 1))
                throw new ArgumentException(string.Format("{0} is an invalid row index.", rowIndex));

            dataGrid.SelectedItems.Clear();
            /* set the SelectedItem property */
            object item = dataGrid.Items[rowIndex]; // = Product X
            dataGrid.SelectedItem = item;

            DataGridRow row = dataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
            if (row == null)
            {
                /* bring the data item (Product object) into view
                 * in case it has been virtualized away */
                dataGrid.ScrollIntoView(item);
                row = dataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
            }
            //TODO: Retrieve and focus a DataGridCell object
            if (row != null)
            {
                DataGridCell cell = GetCell(dataGrid, row, 0);
                if (cell != null)
                    cell.Focus();
            }
        }


 public static DataGridCell GetCell(DataGrid dataGrid, DataGridRow rowContainer, int column)
    {
        if (rowContainer != null)
        {
            DataGridCellsPresenter presenter = FindVisualChild<DataGridCellsPresenter>(rowContainer);
            if (presenter == null)
            {
                /* if the row has been virtualized away, call its ApplyTemplate() method
                 * to build its visual tree in order for the DataGridCellsPresenter
                 * and the DataGridCells to be created */
                rowContainer.ApplyTemplate();
                presenter = FindVisualChild<DataGridCellsPresenter>(rowContainer);
            }
            if (presenter != null)
            {
                DataGridCell cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
                if (cell == null)
                {
                    /* bring the column into view
                     * in case it has been virtualized away */
                    dataGrid.ScrollIntoView(rowContainer, dataGrid.Columns[column]);
                    cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
                }
                return cell;
            }
        }
        return null;
    }
    public static childItem FindVisualChild<childItem>(DependencyObject obj)
where childItem : DependencyObject
    {
        foreach (childItem child in FindVisualChildren<childItem>(obj))
        {
            return child;
        }

        return null;
    }
    public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj)
   where T : DependencyObject
    {
        if (depObj != null)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                if (child != null && child is T)
                {
                    yield return (T)child;
                }

                foreach (T childOfChild in FindVisualChildren<T>(child))
                {
                    yield return childOfChild;
                }
            }
        }
    } 
于 2021-11-12T14:46:07.133 回答