web-dev-qa-db-fra.com

WPF itérer dans une grille de données

Utilisation de WPF C # .NET4.5 à l’aide de visual studio 2012 ulti.

Ancien code Winforms:

foreach (DataGridViewRow paretoRow in ParetoGrid.Rows)
{
       if ((Convert.ToInt32(paretoRow.Cells["CurrentPareto"].Value) < (Convert.ToInt32(paretoRow.Cells["NewPareto"].Value))))
       {
              paretoRow.Cells["pNew"].Value = downArrow
       }
}

Comme vous pouvez le voir, chaque ligne que je parcoure vérifie une cellule spécifique. Si c'est le cas, je remplis une autre cellule. C’était un bon vieux code winforms que j’avais utilisé plusieurs fois auparavant ... cependant ... .. Le passage à WPF était bien plus différent de ce que j’imaginais auparavant.

DataGrid ne contient pas la propriété Row. Au lieu de cela, je pense que vous devez utiliser:

DataGridRow paretoRow in paretogrid.Items

Mais je ne suis toujours pas sûr de qui obtenir maintenant la cellule. 

Ma question est donc la suivante: y at-il des changements de syntaxe à effectuer, si oui où? Ou alors que je commence à croire que les datagrids dans WPF fonctionnent avec des objets plus que des winforms et n’ayant donc pas besoin d’utiliser une propriété appelée "row", si tel est le cas, quelle logique/syntaxe dois-je savoir utiliser dans cet exemple?

Merci pour votre patience les gars, pensez que lorsque je rentrerai chez moi pour le jour férié, je ferai un peu de fouille dans WPF pour voir à quel point c'est différent.

10
lemunk

Je pense que commencer par penser que vous voulez faire est d’obtenir toutes les lignes de votre DataGrid:

public IEnumerable<Microsoft.Windows.Controls.DataGridRow> GetDataGridRows(Microsoft.Windows.Controls.DataGrid grid)
{
    var itemsSource = grid.ItemsSource as IEnumerable;
    if (null == itemsSource) yield return null;
    foreach (var item in itemsSource)
    {
        var row = grid.ItemContainerGenerator.ContainerFromItem(item) as Microsoft.Windows.Controls.DataGridRow;
        if (null != row) yield return row;
    }
}

puis parcourez votre grille:

var rows = GetDataGridRows(nameofyordatagrid); 

foreach (DataGridRow row in rows)  
{  
  DataRowView rowView = (DataRowView)row.Item;
  foreach (DataGridColumn column in nameofyordatagrid.Columns)
  {
      if (column.GetCellContent(row) is TextBlock)
      {
          TextBlock cellContent = column.GetCellContent(row) as TextBlock;
          MessageBox.Show(cellContent.Text);
      }
  } 
18
COLD TOLD

Les gens semblent trop compliquer cela, cela a fonctionné pour moi:

foreach (System.Data.DataRowView dr in yourDataGrid.ItemsSource)
{
     MessageBox.Show(dr[0].ToString());
}
18
Charles Clayton

Dans WPF, vous y allez beaucoup plus dynamique et ObjectOrientated. Vous pouvez lier la colonne "pNew" à une propriété de l'élément que vous avez placé dans la variable DataGrid, qui renvoie downarrow . Si la valeur change, vous pouvez générer l'événement PropertyChanged (Interface INotifyPropertyChanged) et la propriété liée est réévaluée.

Également intéressant pour commencer par WPF est DataTemplate, ControlTemplate, Converter. Converter change la valeur de la propriété en une valeur utilisable pour WPF (par exemple, BoolToVisibility) lorsque la propriété est appelée .DataTemplate et ControlTemplate peut être utilisé pour modifier l'apparence. du contrôle.

Il existe plusieurs bons tutoriels pour WPF. Je recommanderais également d'examiner le modèle MVVM à utiliser comme couche intermédiaire entre votre Businessobject et votre WPF-Control, en particulier pour gérer des tâches telles que ce que vous essayez de faire ici.

1
Patrick

Oui, tu as raison. WPF DataGrid est construit autour d’une meilleure prise en charge de l’utilisation des objets.

Vous pouvez utiliser un ViewModel similaire à celui-ci. Générez-les tous dans une collection, puis définissez cette collection en tant que ItemsSource. Vous devrez également utiliser un ValueConverter si vous souhaitez afficher une image au lieu d'une coche si pNew est vrai/faux.

public class FooViewModel : INotifyPropertyChanged
{
    private int currentPareto;
    public int CurrentPareto 
    {
        get
        {
           return currentPareto;
        }
        set
        { 
            if (currentPareto == value)
                return;

            currentPareto = value;
            OnPropertyChanged("CurrentPareto");
            OnPropertyChanged("pNew");
        }
    }

    private int newPareto;
    public int NewPareto 
    {
        get
        {
           return newPareto;
        }
        set
        { 
            if (newPareto == value)
                return;

            newPareto = value;
            OnPropertyChanged("NewPareto");
            OnPropertyChanged("pNew");
        }
    }

    public bool pNew
    {
        get
        {
            return CurrentPareto < NewPareto;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Modifier

Pour simplifier un peu, vous pouvez utiliser une classe ViewModel de base et utiliser le tissage PropertyChanged. Le code simplifierait ceci:

public class FooViewModel : ViewModelBase
{
    public int CurrentPareto { get; set; }
    public int NewPareto { get; set; }
    public bool pNew { get { return CurrentPareto < NewPareto; } }
}
1
Nick Freeman

Je ne comprends même pas pourquoi il est si compliqué d’obtenir des lignes et leurs valeurs dans une grille de données. C'est un enfer de trouver comment. L'API donne même des noms d'événements amusants et amusants, ce qui n'est pas aussi direct. Pourquoi les gens ne peuvent-ils pas se concentrer sur le niveau de référence et donner ce dont ils ont exactement besoin et non pas toutes sortes d’options différentes sans utilité ni sens du tout? Je veux dire que tout ce dont vous avez besoin est une cuillère et une fourchette bien. Jamais même changé depuis 100 000 ans. Ceci est mon code grâce au type qui a mentionné certaines personnes qui essayent simplement de compliquer les choses à l'extrême et de perdre votre temps.

    private void dtaResultGrid_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        ActivateTestDatagridAccess();
    }

    public async void ActivateTestDatagridAccess()
    {
        try
        {
            await Task.Delay(500);
            foreach (System.Data.DataRowView dr in dtaResultGrid.ItemsSource)
            {
                for (int j = 0; j < dtaResultGrid.Columns.Count; j++)
                {
                    Console.WriteLine(dr[j].ToString());
                }
                Console.Write(Environment.NewLine);
            }
        }
        catch (Exception exrr)
        {
            Console.WriteLine(exrr.ToString());
        }
    }
0