Laden...

WPF Telerik RadGridView - Datenansicht aktualisiert sich nicht

Erstellt von _Cashisclay vor 5 Jahren Letzter Beitrag vor 5 Jahren 3.694 Views
_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren
WPF Telerik RadGridView - Datenansicht aktualisiert sich nicht

Hallo zusammen,

ich hab folgendes Problem :

ich versuche gerade eine ObservableCollection an ein RadGridView (Telerik) zu binden.

Wenn ich das SelectedItem ebenfalls an mein MVVM binde und dort Änderungen tätige, werden diese zwar in die Datenquelle übernommen, allerdings aktualisiert sich mein RadGridView nicht?

Kann mir jemand vielleicht helfen wo mein Fehler aktuell ist :

ViewModel

public System.Collections.ObjectModel.ObservableCollection<View_Extraroehrchen> Extraröhrchen                                          { get { return _Extraröhrchen; } set { _Extraröhrchen = value; OnPropertyChanged("Extraröhrchen"); } }

            protected virtual void OnPropertyChanged(string PropertyName)
            {

                PropertyChanged.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(PropertyName));

            }

WPF

            <telerik:RadGridView    AutoGenerateColumns="False"
                                        IsFilteringAllowed="False" ShowGroupPanel="False"
                                            RowIndicatorVisibility="Collapsed"
                                                telerik:StyleManager.Theme="Windows8Touch"
                                                    ItemsSource="{Binding Extraröhrchen, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                        SelectedItem="{Binding Extraröhrchen_SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">

                    <telerik:GridViewDataColumn DataMemberBinding="{Binding AUSGELAGERT_DATUM, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                    Header="Datum"
                                                        HeaderTextAlignment="Center"
                                                            MinWidth="80">

                        <telerik:GridViewDataColumn.CellTemplate>

                            <DataTemplate>

                                <TextBlock Text="{Binding AUSGELAGERT_DATUM, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

                            </DataTemplate>
                            
                        </telerik:GridViewDataColumn.CellTemplate>

                        <telerik:GridViewDataColumn.CellEditTemplate>

                            <DataTemplate>

                                <Grid>

                                    <Grid.RowDefinitions>

                                        <RowDefinition Height="30"/>

                                    </Grid.RowDefinitions>

                                    <telerik:RadDatePicker Margin="3"
                                                                SelectedValue="{Binding DataContext.Extraröhrchen_Datum, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,
                                                                                             RelativeSource={RelativeSource AncestorType=telerik:RadGridView}}"/>

                                </Grid>

                            </DataTemplate>
                            
                        </telerik:GridViewDataColumn.CellEditTemplate>
                        
                    </telerik:GridViewDataColumn>

</telerik:RadGridView

Wie ich aktuell versuche das ganze zu ändern im Code :

if (ViewModel.Extraröhrchen_Auslagern == true)
                                    {

                                        // --- Datum --- //

                                        ViewModel.Extraröhrchen_Datum = DateTime.Now;

                                        ViewModel.Extraröhrchen_SelectedItem.AUSGELAGERT_DATUM = DateTime.Now;

                                        

                                        //ViewModel.Extraröhrchen.Find(x => x.Praeparat_ID == ViewModel.Extraröhrchen_SelectedItem.Praeparat_ID).AUSGELAGERT_DATUM = DateTime.Now;
               

                                    }

Die Daten werden offensichtlich korrekt übernommen, allerdings wird im RadGridView die Änderung erst angezeigt sobald ich in das Feld klicke und wieder ein anderes auswähle.

Grüße

W
955 Beiträge seit 2010
vor 5 Jahren

View_Extraroehrchen muss INotifyPropertyChanged implementieren.

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Das kommt direkt aus der Datenbank (EntityFramework)

W
955 Beiträge seit 2010
vor 5 Jahren

Das spielt doch keine Rolle. Wenn du Entites direkt an GUI-Elemente bindest müssen diese ebenfalls die GUI benachrichtigen wenn sich Properties ändern damit die GUI sich aktualiseren kann.

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Aber wo soll ich das denn dort einfügen? Die Klasse von wo das Objekt kommt erbt bereits vom DBContext

Vielleicht kannst du mir mit einem Beispiel weiterhelfen?

W
955 Beiträge seit 2010
vor 5 Jahren

Was ist denn View_Extraroehrchen? Wie ist das definiert?

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Ein Objekt aus der Datenbank.

public virtual DbSet<View_Extraroehrchen> View_Extraroehrchens { get; set; }
301 Beiträge seit 2009
vor 5 Jahren

Dann bau ein Objekt ( ViewModel ) welches du stattdessen in deinem RadGridView darstellst. Entities sind nicht dazu gedacht diese direkt in der UI anzuzeigen. Im Zweifelsfall wrap deine Entities zumindest in deinen ViewModels

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Hab ich doch? Ich hab ein ViewModel mit einer ObservableCollection die vom Typ View_Extraroehrchen ist, dieser Typ stammt aus der EntitiyFramework Klasse der dort definitiert ist.

Hat denn in dem Zusammenhang überhaupt schon mal jemand Erfahrung gesammelt? Scheint irgendwie nicht so.

Grüße

4.931 Beiträge seit 2008
vor 5 Jahren

Du sollst View_Extraroehrchen in einer eigene (ViewModel-)Klasse wrappen (welche dann INotifyPropertyChanged implementiert). DB-Objekte (Entities) sollten niemals direkt an die GUI gebunden werden, s.a. [Artikel] Drei-Schichten-Architektur.

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Okay und wie bzw in was wrappe ich es dann am besten?

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren
this.Dispatcher.BeginInvoke(new Action(() => 
	{
		this.Test.Rebind();
	}
), System.Windows.Threading.DispatcherPriority.ApplicationIdle, null);

Immerhin mal etwas was funktioniert ..

301 Beiträge seit 2009
vor 5 Jahren

Was du da machst ist halt keine Lösung deines eigentlichen Problems sondern ein kostenintensiver workaround.

Was wir meinen ist z.B. folgendes:


public class MyViewModelForGrid : INotifyPropertyChanged
{
      public MyViewModelForGrid( MyEntity entityToWrap )
      {
		 this._entityToWrap = entityToWrap;
      }
	  
	  public string MyProperty
	  {
		get { return _entityToWrap.Property; }
		set 
		{ 
			this._entityToWrap.Property = value;
			this.RaisePropertyChanged();
		}
	  }
}

Ist jetzt nur schnell im Editor zusammengeschrieben und daher unvollständig. Aber die Idee ist hoffentlich ersichtlich.

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Naja mit den aktuellen Vorschlägen kam ich noch nicht wirklich weiter und irgendwie muss ich ja voran kommen ..

Und in was oder wie konvertiere ich ein DBSet?

Bist du dir überhaupt sicher dass das RadGridView dann auch die Änderungen bemerkt? Oder vermutest du das ganze einfach nur?

4.931 Beiträge seit 2008
vor 5 Jahren

Wir tippen nur wahllos auf der Tastatur rum und tragen den ganzen Tag einen Aluhut. 🤔

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Wirkt auch so 8o

Wenn mich jemand das nächste mal fragt warum sein Auto nicht funktioniert, sag ich ihm auch einfach reparier es 👍 Sollte ja auf anhieb wissen wie er es umzusetzen hat. :rtfm:

301 Beiträge seit 2009
vor 5 Jahren

Und in was oder wie konvertiere ich ein DBSet?

Das machst du doch schon. In deinem Code oben scheinst du ja eine ObservableCollection zu verwenden. D.h. nach dem Holen von Daten bist du ja gar nicht mehr von deinem DBSet abhängig.

Statt halt einfach die Entities in die Collection zu packen wrapst du sie halt vorher in einem ViewModel.

Technisch bemerkt dein RadGridView eigentlich nichts sondern die WPF Engine sorgt bei dafür, dass Objekte die INotifyPropertyChanged implementieren, auch in der UI aktualisiert werden wenn das Binding stimmt.

Anhand deines Snippets sieht man halt recht wenig was du vor hast und wie bestimmte Dinge bei dir momentan umgesetzt sind. z.b. hab ich keine Ahnung wie du momentan überhaupt Daten bis zu deiner UI bringst.

Sprich: Ja wir müssen hier sehr viel Vermuten weil wir nicht an deinem Projekt beteiligt sind und nicht in deinen Kopf schauen können 😃. Viele Probleme du grade hast hatten wir auch schon 100x und haben gewisse Standardlösungen parat. Dir sollte aber klar sein, dass wir hier nur gewisse Lösungsansätze geben können und du es ansonsten schon selbst schaffen musst die Ansätze in die Tat umzusetzen.

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Statt halt einfach die Entities in die Collection zu packen wrapst du sie halt vorher in einem ViewModel.

Also ich packe meine Entities in ein extra ViewModel und befülle meine ObservableCollection dann mit dem ViewModel oder wie?

Anhand deines Snippets sieht man halt recht wenig was du vor hast und wie bestimmte Dinge bei dir momentan umgesetzt sind. z.b. hab ich keine Ahnung wie du momentan überhaupt Daten bis zu deiner UI bringst.

Aber das ist doch eine Aussage mit der ich arbeiten kann.

mein aktuelles ViewModel :

public System.Collections.ObjectModel.ObservableCollection<View_Extraroehrchen> Extraröhrchen                                          { get { return _Extraröhrchen; } set { _Extraröhrchen = value; OnPropertyChanged("Extraröhrchen"); } }

            protected virtual void OnPropertyChanged(string PropertyName)
            {

                PropertyChanged.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(PropertyName));

            }

meine Klasse :

                    this.DataContext = ViewModel;

                        ViewModel.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(OnPropertyChanged);

                            set_Default_Values();


Befüllung der Daten


ViewModel.Extraröhrchen = Vita34.Data.VitaLab.VitaLab3.Liste.Liste.Get.GetViewExtraroehrchen(
                                                                                                                             ViewModel.Extraröhrchen_Filterbereich_Tagesliste_Datum,
                                                                                                                             ViewModel.Extraröhrchen_Filterbereich_Tagesliste_Datum.AddDays(1)
                                                                                                                            );

Anbindung an die Oberfläche

            <telerik:RadGridView    AutoGenerateColumns="False"
                                        IsFilteringAllowed="False" ShowGroupPanel="False"
                                            RowIndicatorVisibility="Collapsed"
                                                telerik:StyleManager.Theme="Windows8Touch"
                                                    ItemsSource="{Binding Extraröhrchen, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                        SelectedItem="{Binding Extraröhrchen_SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

Bearbeitung der Daten

            
                            if (ViewModel.IsWorking == false)
                            {

                                if (ViewModel.Extraröhrchen_SelectedItem != null)
                                {

                                    ViewModel.Extraröhrchen_SelectedItem.AUSGELAGERT_VON = ViewModel.Extraröhrchen_Bearbeiter;

                                }

                            }

4.931 Beiträge seit 2008
vor 5 Jahren

Die Antwort von KroaX ("class MyViewModelForGrid") gilt immer noch.
Du wärst schon lange fertig, wenn du es nicht dauernd hinterfragen würdest Warum eigentlich? Verstehst du die Grundlagen des DataBindings (PropertyChanged) nicht?

301 Beiträge seit 2009
vor 5 Jahren

Versuch dich ein bisschen in unsere Lage zu versetzen wenn du eine Frage stellst 😃

Vita34.Data.VitaLab.VitaLab3.Liste.Liste.Get.GetViewExtraroehrchen(...) 

Wir können nicht verstehen was da passiert. Offensichtlich kommt da eine ObservableCollection zurück. Aber was in dieser Methode passiert und wie deine Entities in diese ObservableCollection gelangen sehen wir nicht. Dort ist aber scheinbar ein möglicher Platz für dein Wrapping.

Also ich packe meine Entities in ein extra ViewModel und befülle meine ObservableCollection dann mit dem ViewModel oder wie?

Jede deiner Entities ist ein eigenes ViewModel. Und ja deine ObservableColleciton ist dann eine Auflistung dieser ViewModels.

Mir scheint auch, dass dir sehr viele Grundlagen zu WPF, XAML und Databinding fehlen. Niemand setzt voraus, dass du das schon alles weißt wenn du hier eine Frage stellst aber zu sehr vielen Dingen ( grade zu Grundlagen ) findet man mit Google auch selbst schnell eine Antwort.

https://wpftution.blogspot.com/2012/05/mvvm-sample-using-datagrid-control-in.html

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Wir können nicht verstehen was da passiert. Offensichtlich kommt da eine ObservableCollection zurück. Aber was in dieser Methode passiert und wie deine Entities in diese ObservableCollection gelangen sehen wir nicht. Dort ist aber scheinbar ein möglicher Platz für dein Wrapping.

using (VitaLab3Entities VitaLab = new VitaLab3Entities())
                {

                    var Extraröhrchen = VitaLab.View_Extraroehrchens.Where(x => x.ANNAHME_DATUM > AnnahmeDatum && x.ANNAHME_DATUM < AnnahmeDatumBis).OrderBy(x => x.ANNAHME_DATUM);

                    return new System.Collections.ObjectModel.ObservableCollection<View_Extraroehrchen>(Extraröhrchen);

                }
301 Beiträge seit 2009
vor 5 Jahren

Wäre schon gut wenn du es selbst löst.

https://stackoverflow.com/questions/9881790/how-to-design-viewmodel

Das sind echt absolute Basics der Programmierung zu verstehen was ein Wrapper ist oder wie man LINQ verwendet wenn man es verwenden möchte. Einfach drauf los programmieren funktioniert bis zu einem gewissen Grad aber irgendwann muss man doch etwas mehr darüber lesen und verstehen was man da eigentlich macht.

Mehr kann ich dir da jetzt auch nicht an die Hand geben. In dem Link ist in ähnlicher Weise erklärt was du tun müsstest.

5.657 Beiträge seit 2006
vor 5 Jahren

Hier geht es wirklich um die grundlegenden Dinge im Umgang mit WPF. Die sind hier erklärt: [Artikel] MVVM und DataBinding

Weeks of programming can save you hours of planning

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Schließt einfach den Thread das ist sinnlos 👍

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

So war es wohl auch nicht gemeint .. 🙁

Datenquelle

            public static List<View_Extraroehrchen> return_Extraröhrchen()
            {
                try
                {

                    using (VitaLab3Entities VitaLab = new VitaLab3Entities())
                    {

                        var x = VitaLab.View_Extraroehrchens.ToList();

                        return x;

                    }

                }
                catch (Exception ex)
                {

                    MessageBox.Show(ex.StackTrace.ToString());

                }

                return null;

            }

ViewModel



                private ObservableCollection<ViewModel_Extraröhrchen_Test> _Test;

                public ObservableCollection<ViewModel_Extraröhrchen_Test> Test { get { return _Test;} set { _Test = value; OnPropertyChanged("Test"); } }

    public class ViewModel_Extraröhrchen_Test
    {

        public string Format_Praeparat_ID { get; set; }

        public DateTime? AUSGELAGERT_DATUM { get; set; }


    }


Window

ViewModel.Test = new System.Collections.ObjectModel.ObservableCollection<Vita34.VitaLab.Windows.VitaLab.ViewModel.ViewModel_Extraröhrchen_Test>(Vita34.Data.VitaLab.VitaLab3.Sammellisten.Extraröhrchen.Extraröhrchen.Get.return_Extraröhrchen().Select(x => new VitaLab.ViewModel.ViewModel_Extraröhrchen_Test
                                                                                                                                                            {
                                                                                                                                                                Format_Praeparat_ID = x.Format_Praeparat_ID,
                                                                                                                                                                AUSGELAGERT_DATUM = x.AUSGELAGERT_DATUM
                                                                                                                                                            }
                                                                                                                                                        ));
_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Yei ich habs 😁

16.807 Beiträge seit 2008
vor 5 Jahren

Wenn Du schon Deutsch programmierst, was an für sich schon schlimm genug ist, lass doch wenigstens die Umlaute weg... 👍

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Er zeigt mir jetzt zwar schön meine Änderungen im RadGridView an, allerdings wenn ich vom Code aus etwas im ViewModel setze wird irgendwie kein PropertyChanged Event ausgelöst, er springt irgendwie gar nicht erst in den Set Bereich ..

ViewModel Extraröhrchen

                private ObservableCollection<ViewModel_Extraröhrchen_RadGridView> _Extraröhrchen_RadGridView;

                private ViewModel_Extraröhrchen_RadGridView _Extraröhrchen_RadGridView_SelectedItem;

                public ObservableCollection<ViewModel_Extraröhrchen_RadGridView> Extraröhrchen_RadGridView      { get { return _Extraröhrchen_RadGridView; } set { _Extraröhrchen_RadGridView = value; OnPropertyChanged("Extraröhrchen_RadGridView"); } }

                public ViewModel_Extraröhrchen_RadGridView Extraröhrchen_RadGridView_SelectedItem               { get { return _Extraröhrchen_RadGridView_SelectedItem; } set { _Extraröhrchen_RadGridView_SelectedItem = value; OnPropertyChanged("Extraröhrchen_RadGridView_SelectedItem"); } }

ViewModel_Extraröhrchen_RadGridView

        public List<Vita34.Data.VitaLab.Database.TNK_TANK>  Extraröhrchen_RadGridView_TANK                  { get { return _Extraröhrchen_RadGridView_TANK; }               set {_Extraröhrchen_RadGridView_TANK = value; } }

        public int                                          Extraröhrchen_RadGridView_TANK_SelectedIndex    { get { return _Extraröhrchen_RadGridView_TANK_SelectedIndex; } set { _Extraröhrchen_RadGridView_TANK_SelectedIndex = value;    OnPropertyChanged("Extraröhrchen_RadGridView_TANK_SelectedIndex"); } } 

        public string                                       Extraröhrchen_RadGridView_TANK_NAME             { get { return _Extraröhrchen_RadGridView_TANK_NAME; }          set { _Extraröhrchen_RadGridView_TANK_NAME = value;             OnPropertyChanged("Extraröhrchen_RadGridView_TANK_NAME"); } }

Window

ViewModel.Extraröhrchen_RadGridView_SelectedItem.Extraröhrchen_RadGridView_TANK = Vita34.Data.VitaLab.Helper.Get.DropDownTanks("E");

XAML

                        <telerik:GridViewDataColumn.CellEditTemplate>

                            <DataTemplate>

                                <ComboBox   Margin="3"
                                                VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
                                                    ItemsSource="{Binding Extraröhrchen_RadGridView_TANK}"
                                                        DisplayMemberPath="TANK_NAME"
                                                            SelectedIndex="{Binding Extraröhrchen_RadGridView_SelectedItem.Extraröhrchen_RadGridView_TANK_SelectedIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

                            </DataTemplate>
                            
                        </telerik:GridViewDataColumn.CellEditTemplate>

Liegt es daran das ich im SelectedItem die Werte befülle und er dann irgendwie den Bezug verliert? Seltsamerweise lässt sich vom Code aus die Datenquelle befüllen, was er auch richtig anzeigt.

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Oder bring ich da wieder etwas durcheinander?

Brauch das neue ViewModel auch nochmal ein INotifyPropertyChanged?

Edit : Jup, dachte es reicht wenn es vom ersten erbt.

1.040 Beiträge seit 2007
vor 5 Jahren

Wenn das ViewModel, von dem du erbst, bereits INotifyPropertyChanged implementiert, dann braucht das andere ViewModel es nicht mehr implementieren.

Evtl. solltest du dir die Grundlagen nochmal in einem minimalen Testprojekt anschauen.
Ich zumindest bin bei deinen ganzen ViewModel_Extraröhrchen_RadGridView_View_View_Model_PiPaPo ausgestiegen... 😉

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 5 Jahren

Ging leider nicht, obwohl es im anderen bereits implementiert war. 🤔

301 Beiträge seit 2009
vor 5 Jahren

wenn ich vom Code aus etwas im ViewModel setze wird irgendwie kein PropertyChanged Event ausgelöst, er springt irgendwie gar nicht erst in den Set Bereich

Vom Code aus wo? Deine Formulierung ist hier nicht genau genug.

  • Welche Aktion führst du in der UI aus?
  • Welcher Methodenaufruf folgt daraus?
  • Was wird nicht ausgeführt, was du aber erwartest?
  • Bis wohin konntest du deine Aktion im Code durch debuggen nachvollziehen, und ab wo nicht mehr?

Bitte gib keine Antwort bis du nicht auf jede der Fragen eine Antwort hast.

1.040 Beiträge seit 2007
vor 5 Jahren

Ging leider nicht, obwohl es im anderen bereits implementiert war. 👶

Dann liegt was anderes im Argen.