web-dev-qa-db-fra.com

Événement de modification de la valeur de la cellule WPF DataGrid

J'ai une configuration qui ressemble à ceci:

// myDG is a DataGrid whose columns are DataGridTextColumn
ObservableCollection<MyItem> myOC;
// myOC is populated with some new MyItem
myDG.ItemsSource = myOC;

MyItem implémente INotifyPropertyChanged. Comment capturer correctement lorsque l'utilisateur entre une valeur dans une cellule?

J'ai essayé d'attraper PropertyChanged sur les MyItems, mais je mets également à jour périodiquement les valeurs en arrière-plan (l'idée est que lorsque l'utilisateur modifie manuellement la valeur, un indicateur est déclenché qui indique au calcul périodique pour éviter d'écraser les données saisies manuellement). Donc PropertyChanged attrape tout, y compris les mises à jour périodiques, dont je ne veux pas. Je suppose qu'il est possible de faire ce travail (en définissant un indicateur lorsque je fais le calcul périodique, puis en vérifiant l'absence d'indicateur sur le gestionnaire d'événements PropertyChanged - mais je veux savoir s'il existe une solution plus simple.)

J'ai essayé d'attraper myDG.CurrentCellChanged mais cela se déclenche à chaque fois que l'utilisateur modifie la sélection de cellules, pas spécifiquement lorsqu'il modifie le contenu des cellules.

Edit: Voici le XAML:

<DataGrid x:Name="myDG" ItemsSource="{Binding}" AutoGenerateColumns="False" Margin="10,10,182,0" VerticalAlignment="Top" Height="329" ClipboardCopyMode="IncludeHeader">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Col1" Binding="{Binding Prop1}" IsReadOnly="True"/>
        <DataGridTextColumn Header="Col2" Binding="{Binding Prop2}" IsReadOnly="False"/>
    </DataGrid.Columns>
</DataGrid>

Voici l'implémentation MyItem (utilise Fody/PropertyChanged ):

[ImplementPropertyChanged]
class MyItem : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string Prop1 { get; set; }
    public string Prop2 { get; set; }

    public MyItem()
    {
        Prop1 = Prop2 = "";
    }
}
17
jcai

La solution était d'attraper l'événement CellEditEnding.

// In initialization
myDG.CellEditEnding += myDG_CellEditEnding;

void myDG_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    if (e.EditAction == DataGridEditAction.Commit)
    {
        var column = e.Column as DataGridBoundColumn;
        if (column != null)
        {
            var bindingPath = (column.Binding as Binding).Path.Path;
            if (bindingPath == "Col2")
            {
                int rowIndex = e.Row.GetIndex();
                var el = e.EditingElement as TextBox;
                // rowIndex has the row index
                // bindingPath has the column's binding
                // el.Text has the new, user-entered value
            }
        }
    }
}
28
jcai

Vous pouvez y parvenir en utilisant l'événement CellEditEnding et une autre chose est dans DataGridTextColumn devez ajouter certains attributs comme ci-dessous: -

<DataGrid x:Name="myDG" CellEditEnding="myDG_CellEditEnding"  ItemsSource="{Binding}" AutoGenerateColumns="False" Margin="10,10,182,0" VerticalAlignment="Top" Height="329" ClipboardCopyMode="IncludeHeader">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Col1" Binding="{Binding Prop1}" 
 IsReadOnly="True"/>
 <DataGridTextColumn x:Name="dataGridTextColumn"Header="Col2" Binding="{Binding Prop2,  UpdateSourceTrigger=LostFocus, Mode=TwoWay}" Width="*" />
    </DataGrid.Columns>
</DataGrid>

EN C #

 private void myDG_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) {
            string prop1 = (e.Row.Item as DataRowView).Row[1].ToString();
        }
0
Jay Kashyap