WPF Datagrid ensemble de la ligne sélectionnée

comment utiliser le Datagrid.SelectedItem pour sélectionner une ligne par programmation?

Est-ce que je dois d'abord créer un IEnumerableDataGridRow objets et de passer la ligne correspondante à ce SelectedItem propriété ou comment faire?

EDIT:

j'ai besoin de faire correspondre le contenu de la cellule de la première colonne de la cellule avec un TextBox.Text d'abord, avant de sélectionner la ligne.

15
demandé sur Dave Clemmer 2009-12-29 21:24:29

8 réponses

s'il vous plaît vérifier si le code ci-dessous fonctionne pour vous; il itère à travers les cellules de la première colonne de datagris et vérifie si le contenu de la cellule est égal à la zone de texte.valeur de texte et sélectionne la ligne.

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

j'espère que cette aide, ce qui concerne

35
répondu serge_gubenko 2009-12-29 19:40:06

Vous n'avez pas besoin de parcourir le DataGrid les lignes, vous pouvez atteindre votre objectif avec une solution plus simple. Afin de correspondre à votre ligne vous pouvez itérer à travers votre collection qui était liée à votre DataGrid.ItemsSource propriété puis assignez cet élément à vous DataGrid.SelectedItem propriété programmatique, alternativement vous pouvez l'ajouter à votre DataGrid.SelectedItems collection si vous souhaitez autoriser l'utilisateur à sélectionner plus d'une ligne. Voir le code ci-dessous:

<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;
    }
}
21
répondu Mohammed A. Fadil 2012-06-07 06:16:54

c'est un peu plus compliqué de faire ce que vous essayez de faire que ce que je préférerais, mais c'est parce que vous ne liez pas directement un DataGridDataTable.

Lorsque vous liez DataGrid.ItemsSourceDataTable, vous êtes vraiment le liant à la valeur par défaut DataView, pas à la table elle-même. C'est pourquoi, par exemple, vous ne devez rien faire pour faire un DataGrid trier les lignes lorsque vous cliquez sur l'en - tête d'une colonne-cette fonctionnalité est stockée dans DataView et DataGrid sait comment y accéder (par le biais de l' IBindingList interface).

DataView implémente IEnumerable<DataRowView> (plus ou moins), et le DataGrid remplit ses éléments en itérant sur ceci. Cela signifie que lorsque vous avez lié DataGrid.ItemsSourceDataTable, son SelectedItem propriété sera une DataRowView, pas DataRow.

Si vous savez tout cela, c'est assez simple de construire une classe wrapper qui permet d'exposer les propriétés que vous pouvez lier à. Il y a trois clés propriétés:

  • Table, le DataTable,
  • Row, une propriété bidirectionnelle de type bindable DataRowView et
  • SearchText, une propriété string qui, lorsqu'elle est définie, trouvera la première correspondance DataRowView dans la vue par défaut de la table, définissez le Row propriété, et de soulever PropertyChanged.

Il ressemble à ceci:

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

et voici XAML qui l'utilise:

<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>
7
répondu Robert Rossney 2011-09-09 03:50:34

j'ai cherché la solution à un problème similaire et peut-être que ma façon vous aidera ainsi que tous ceux qui font face avec elle.

j'ai utilisé SelectedValuePath="id" dans le code XAML définition de grille de données, et programaticaly seule chose que j'ai à faire est de définir DataGrid.SelectedValue à la valeur souhaitée.

je sais que cette solution a des avantages et des inconvénients, mais dans le cas précis est rapide et facile.

cordialement

Marcin

6
répondu Marcin Sasin 2012-08-20 12:29:42

// En Général pour Accéder à toutes les lignes //

foreach (var item in dataGrid1.Items)
{
    string str = ((DataRowView)dataGrid1.Items[1]).Row["ColumnName"].ToString();
}

//Pour Accéder À Des Lignes Sélectionnées //

private void dataGrid1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    try
    {
        string str = ((DataRowView)dataGrid1.SelectedItem).Row["ColumnName"].ToString();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}
3
répondu Shan 2012-10-03 18:33:43

j'ai changé le code de serge_gubenko et il fonctionne mieux

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;
    }
}
1
répondu Marian Brestovansky 2015-12-30 14:05:33

je suis tombé sur cet article de TechNet assez récent (par rapport à l'âge de la question) qui inclut certaines des meilleures techniques que j'ai pu trouver sur le sujet:

WPF: par programmation en Sélectionnant et en Concentrant une Ligne ou une Cellule dans un DataGrid

il comprend des détails qui devraient couvrir la plupart des exigences. Il est important de se rappeler que si vous spécifiez des gabarits personnalisés pour le DataGridRow pour certaines lignes, ceux-ci n'auront pas de DataGridCells à l'intérieur et alors les mécanismes normaux de sélection de la grille ne fonctionnent pas.

vous aurez besoin d'être plus précis sur la source de données que vous avez donné la grille pour répondre à la première partie de votre question, comme les autres l'ont déclaré.

0
répondu Andre Luus 2015-01-14 13:31:53

si quelqu'un trébuchant ici a des problèmes avec la sélection de grille interne qui se produit après Onselection changed - après avoir essayé sans succès tous les setters de sélection pendant une douzaine d'heures la seule chose qui a fonctionné pour moi était recharger et repopuler DataGrid avec l'article sélectionné. Pas élégant du tout, mais à ce point je ne suis pas sûr si une meilleure solution existe dans ma situation.

datagrid.ItemsSource = null
datagrid.ItemsSource = items;
datagrid.SelectedItem = selectedItem;
0
répondu Mindaugas-kun 2017-07-24 12:12:04