Laden...

Wie mache ich im einem DataGrid eine Spalte für eine Berechnung von zwei Werten?

Erstellt von Qt21580 vor 7 Jahren Letzter Beitrag vor 7 Jahren 2.847 Views
Q
Qt21580 Themenstarter:in
204 Beiträge seit 2005
vor 7 Jahren
Wie mache ich im einem DataGrid eine Spalte für eine Berechnung von zwei Werten?

Hallo zusammen,

Ich habe ein Problem mit dem DataGrid.
Kann mir jemand einen Tip geben wie man in einem dataGrid eine Spalte für eine Berechnung von zwei Werten macht mittels MVVM Pattern.



        <DataGrid x:Name="dataGrid" Grid.Row="0" ItemsSource="{Binding Path=SelectedJobsToFinish}" Margin="10,10,10,0" AutoGenerateColumns="False" 
                  FontSize="16" HeadersVisibility="All" CanUserAddRows="False" CanUserDeleteRows="False" 
                  SelectedItem="{Binding SelectedJobToFinish}" Height="286" VerticalAlignment="Top">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding AuftragLfdNr}" ClipboardContentBinding="{x:Null}" Header="Auftragsnummer" IsReadOnly="True" Width="150"/>
                <DataGridTextColumn Binding="{Binding Sachnummer}" ClipboardContentBinding="{x:Null}" Header="Sachnummer" IsReadOnly="True" Width="130"/>
                <DataGridTextColumn Binding="{Binding Benennung}" ClipboardContentBinding="{x:Null}" Header="Benennung" IsReadOnly="True" Width="200"/>
                <DataGridTextColumn Binding="{Binding Anzahl}" ClipboardContentBinding="{x:Null}" Header="Anzahl" Width="80" />
                <DataGridTextColumn ClipboardContentBinding="{x:Null}" Header="Anzahl Neu" Width="100">
                    <DataGridTextColumn.Binding>
                        <Binding Path="tempAnzahl">
                            <Binding.ValidationRules>
                                <validation:CellDataInfoValidationRule ValidationStep="UpdatedValue" />
                            </Binding.ValidationRules>
                        </Binding>
                    </DataGridTextColumn.Binding>
                </DataGridTextColumn>
                <DataGridTextColumn Binding="{Binding Path=Schrott, UpdateSourceTrigger=PropertyChanged}" ClipboardContentBinding="{x:Null}" Header="Schrott" Width="80" />
                <!--<DataGridTextColumn Binding="{Binding XPath=Total}" ClipboardContentBinding="{x:Null}" Header="Schrott1" Width="80" />-->
            </DataGrid.Columns>
        </DataGrid>


Das Bild ist nicht ganz aktuell, sind einige Testspalten dazugekommen.

Wenn ich in das Feld Anzahl Neu einen Wert eingebe soll das Feld Schrott die Differenz zwischen Anzahl und Anzahl neu errechnen. Ich habe es soweit geschafft das dieser Wert im Model errechnet wird nur das Problem das ich habe ist das der errechnete Wert nicht in meinem Datagrid angezeigt wird erst nachdem ich in das Feld Schrott geklickt habe bekomme ich diesen zu sehen.

Hier ein Ausschnitt aus meinem ViewModel.



        #region Properties
        private ObservableCollection<WZS_Auftrag> p_selectedJobs;
        public ObservableCollection<WZS_Auftrag> SelectedJobsToFinish
        {
            get { return p_selectedJobs; }
            set
            {
                if (value == p_selectedJobs) return;
                p_selectedJobs = value;
                SelectedJobToFinish = p_selectedJobs[0];
                //SelectedJobToFinish.tempSchrott = 12;
                RaisePropertyChanged();
            }
        }

        private WZS_Auftrag p_selectedJob;
        public WZS_Auftrag SelectedJobToFinish
        {
            get { return p_selectedJob; }
            set
            {
                if (value == p_selectedJob) return;
                p_selectedJob = value;
                //p_Anz = p_selectedJob.Anzahl;
                //p_selectedJob.tempSchrott = 12;
                RaisePropertyChanged();
            }
        }
        #endregion Properties


Die Berechnung habe ich schon überall gemacht nur leider funktioniert nix.

Bitte um einen Denkanstoss komme hier einfach nicht mehr weiter auch wenn es wahrscheinlich nur eine Lapalie ist für jemanden ist der das öfter macht.

In WinForms gibt es für sowas im DataSet oder Table eine Expression Funktion, wie mache ich sowas mit WPF/MVVM denn da gibt es keine Expression zumindest habe ich nix gefunden.....

Hinweis von Coffeebean vor 7 Jahren

Kannst du bitte das nächste Mal einen richtigen Titel wählen? Mit "DataSet" kann niemand was anfangen, es beschreibt dein Problem nichtmal ansatzweise

F
10.010 Beiträge seit 2004
vor 7 Jahren

Indem du im VM eben ein Property einbaust das die Berechnung durchführt.

2.207 Beiträge seit 2011
vor 7 Jahren

Hallo Qt21580,

Bitte wähle das nächste Mal einen besseren Titel. [Hinweis] Wie poste ich richtig?

Dein GridView bzw. deine UI sollte diese Berechnung gar nicht durchführen. Wie willst du das testen?

Mach, wie FZelle es sagt, ein Property im ViewModel, was dir die Informationen zur Verfügung stellt und binde daran.

Gruss

Coffeebean

Q
Qt21580 Themenstarter:in
204 Beiträge seit 2005
vor 7 Jahren

Hallo FZelle

Das habe ich auch schon versucht nur klappt das bei mir irgndwie nicht.



        <DataGrid x:Name="dataGrid" Grid.Row="0" ItemsSource="{Binding Path=SelectedJobsToFinish}" Margin="10,10,10,0" AutoGenerateColumns="False" 
                  FontSize="16" HeadersVisibility="All" CanUserAddRows="False" CanUserDeleteRows="False" 
                  SelectedItem="{Binding SelectedJobToFinish}" Height="286" VerticalAlignment="Top">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding AuftragLfdNr}" ClipboardContentBinding="{x:Null}" Header="Auftragsnummer" IsReadOnly="True" Width="150"/>
                <DataGridTextColumn Binding="{Binding Sachnummer}" ClipboardContentBinding="{x:Null}" Header="Sachnummer" IsReadOnly="True" Width="130"/>
                <DataGridTextColumn Binding="{Binding Benennung}" ClipboardContentBinding="{x:Null}" Header="Benennung" IsReadOnly="True" Width="200"/>
                <DataGridTextColumn Binding="{Binding Anzahl}" ClipboardContentBinding="{x:Null}" Header="Anzahl" Width="80" />
                <DataGridTextColumn x:Name="colAnzahl_Neu" ClipboardContentBinding="{x:Null}" Header="Anzahl Neu" Width="100">
                    <DataGridTextColumn.Binding>
                        <Binding Path="tempAnzahl">
                            <Binding.ValidationRules>
                                <validation:CellDataInfoValidationRule ValidationStep="UpdatedValue" />
                            </Binding.ValidationRules>
                        </Binding>
                    </DataGridTextColumn.Binding>
                </DataGridTextColumn>
                <DataGridTextColumn Binding="{Binding Path=Total}" Header="Schrott" Width="80" />
                <!--<DataGridTextColumn Binding="{Binding XPath=Total}" ClipboardContentBinding="{x:Null}" Header="Schrott1" Width="80" />-->
            </DataGrid.Columns>


Die Property wird einfach nie aufgerufen



        private int? _total = 0;
        public int? Total
        {
            get { return _total; }
            set
            {
                _total = value;
                RaisePropertyChanged();
            }
        }


Wenn ich dann per Hand etwas in die Spalte Schrott eintrage dann bekomme ich zum dank diese Fehlermeldung: Two-way binding requires Path or XPath.

Habe einen Trigger eingefügt......
der auch nicht Funktioniert



            <i:Interaction.Triggers>
                <i:EventTrigger EventName="CellEditEnding">
                    <i:InvokeCommandAction Command="{Binding Path=TextChangedCommand}"  />
                </i:EventTrigger>
            </i:Interaction.Triggers>






        public RelayCommand<object> TextChangedCommand { get; private set; }
        private void ExecuteTextChangedCommand(object value)
        {
            Total = 11;
            RaisePropertyChanged("Total");

        }


Q
Qt21580 Themenstarter:in
204 Beiträge seit 2005
vor 7 Jahren
WPF DataGrid

Hallo Coffeebean
Das habe ich ja versucht nur leider ohne Erfolg. Kann mir vielleicht jemand ein kleines Beispiel zeigen wie ich das angehe.

Wie gesagt, die Berechnung wird ja gemacht nur das DataGrid zeigt das Ergebniss nicht an.

F
10.010 Beiträge seit 2004
vor 7 Jahren

Warum meinst du da ein Nullable<Int> benutzen zu müssen?
Und warum "{Binding Path=Total}"?

Wann ändert WPF den Wert im Binding für Total?
Wenn es die Benachrichtigung PropertyChanged für "Total" bekommt.

Wo wirfst du die?
Wenn du sie nirgendwo wirfst, macht es natürlich nix.
Jede Berechnung, jedes Property das Einfluss hat, muss auch RaisePropertyChanged("Total") aufrufen.

Q
Qt21580 Themenstarter:in
204 Beiträge seit 2005
vor 7 Jahren

Warum meinst du da ein Nullable<Int> benutzen zu müssen?

Nullable<Int> weil ich die Daten aus einer DB lese und ich Probleme beim Casten hatte.

Und warum "{Binding Path=Total}"?

Binding="{Binding Path=Total}" soll eigentlich die Bindung zur Property in meinem VM sein.

Wann ändert WPF den Wert im Binding für Total?

Das ist ja mein Problem ich weiss es nicht.

Wo wirfst du die? ICh dachte mir bei CellEditEnding



        <DataGrid x:Name="dataGrid" Grid.Row="0" ItemsSource="{Binding Path=SelectedJobsToFinish}" Margin="10,10,10,0" AutoGenerateColumns="False" 
                  FontSize="16" HeadersVisibility="All" CanUserAddRows="False" CanUserDeleteRows="False" 
                  SelectedItem="{Binding SelectedJobToFinish}" Height="286" VerticalAlignment="Top">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding AuftragLfdNr}" ClipboardContentBinding="{x:Null}" Header="Auftragsnummer" IsReadOnly="True" Width="150"/>
                <DataGridTextColumn Binding="{Binding Sachnummer}" ClipboardContentBinding="{x:Null}" Header="Sachnummer" IsReadOnly="True" Width="130"/>
                <DataGridTextColumn Binding="{Binding Benennung}" ClipboardContentBinding="{x:Null}" Header="Benennung" IsReadOnly="True" Width="200"/>
                <DataGridTextColumn Binding="{Binding Anzahl}" ClipboardContentBinding="{x:Null}" Header="Anzahl" Width="80" />
                <DataGridTextColumn x:Name="colAnzahl_Neu" ClipboardContentBinding="{x:Null}" Header="Anzahl Neu" Width="100">
                    <DataGridTextColumn.Binding>
                        <Binding Path="tempAnzahl">
                            <Binding.ValidationRules>
                                <validation:CellDataInfoValidationRule ValidationStep="UpdatedValue" />
                            </Binding.ValidationRules>
                        </Binding>
                    </DataGridTextColumn.Binding>
                </DataGridTextColumn>
                <DataGridTextColumn Binding="{Binding Path=Total}" Header="Schrott" Width="80" />
                <!--<DataGridTextColumn Binding="{Binding XPath=Total}" ClipboardContentBinding="{x:Null}" Header="Schrott1" Width="80" />-->
            </DataGrid.Columns>


            <i:Interaction.Triggers>
                <i:EventTrigger EventName="CellEditEnding">
                    <i:InvokeCommandAction Command="{Binding Path=TextChangedCommand}"  />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </DataGrid>


Hinweis von Coffeebean vor 7 Jahren

Kannst du bitte die richtigen Code-Tags nutzen?

P
1.090 Beiträge seit 2011
vor 7 Jahren

Ich gehe mal davon aus das sich der Wert bei der Eingabe von "Neue Anzahl" ändern soll. Da kannst du dann einfach im VM eine Property anlegen und dort den Wert von Total endern.

 private int _NeueAnzahl = 0;
        public int  NeueAnzahl 
        {
            get { return _NeueAnzahl ; }
            set
            {
                _NeueAnzahl = value;
                Total = _NeueAnzahl;
                RaisePropertyChanged();
            }
        } 

p.s.
Wenn du Total aus der DB ließt und es eine Property des VM ist, setzt du nicht das MVVM Pattern um.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

Q
Qt21580 Themenstarter:in
204 Beiträge seit 2005
vor 7 Jahren

Ja das ist richtig.

Aus der DB wird eine Property Anzahl gelesen die ist in meinem Model.
Ich habe aber in meinem Model noch die Propertys NeueAnzahl und Schrott die
werden aber nicht von er DB befüllt sondern diese Werte brauche ich zum zurückschreiben.

Wenn ich in meinem VM eine Property habe an die ich binde kommt folgende
Fehlermeldung: Two-way binding requires Path or XPath.

Mein Model



        public int? Anzahl { get; set; } //Nullable<int> weil der eben null sein kann.
        public int tempSchrott { get; set; } //Schrott sollte errechnet werden.
        public int tempAnzahl { get; set; } //NeueAnzahl


So habe ich das schon gemacht nur geht's nicht.?????

P
1.090 Beiträge seit 2011
vor 7 Jahren

Schau mal ob es richtig geschrieben ist und das das Property in der gleichen Klasse ist wie die anderen gebundenen Eigenschaften.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern