none
Binding Aktualisierung RRS feed

  • Frage

  • Hallo!

    Ich habe eine (typisierte) Datatable, dessen DefaultView ich dem DataContext eines WPF-Fensters zuordne.

    private void wndInfo_Loaded(object sender, RoutedEventArgs e)
            {
    ...
                this.DataContext = tabBenutzer.DefaultView;   // Benutzer-Berechtigung(en) dem gesamten Fenster zur Verfügung stellen
    }

    In einem anderen Fenster ändere ich die zugrunde liegenden SQL-Daten. Nach dem schließen des Änderungsfensters aktualisiere ich die zentrale Tabelle und damit auch die DefaultView.

    Anruf_Info.BenutzerRechte wndBenRechte = new BenutzerRechte();      // Neues Fenster der Benutzer-Berechtigungen initalisieren
    wndBenRechte.BenID = rowBEN_Berechtigung.ID;                        // Akt. Ben-ID übergeben
    wndBenRechte.ShowDialog();                                          // Benutzer-Rechte-Fenster anzeigen
    // Benutzer-Berechtigungen aktualisieren
    DS_AINFOTableAdapters.VIEW_BENUTZER_TableAdapter adap = new DS_AINFOTableAdapters.VIEW_BENUTZER_TableAdapter();
    tabBenutzer = adap.GetData(zBenutzer);

    Da die DefaultView der DataTable die  INotifyCollectionChanged-Schnittstelle implementiert, müßten doch die geänderten Daten über das Binding angezeigt werden! Die DefaultView stellt nach der Aktualisierung definitiv die neuen Daten zur Verfügung.

    Hat jemand einen Hinweis, wie ich die Aktualisierung "übernehme"???

    Fred.

    • Bearbeitet perlfred Freitag, 12. Oktober 2012 06:33 Formatierung
    Donnerstag, 11. Oktober 2012 14:51

Antworten

  • Hallo Fred,

    da hast Du einen kleinen Denkfehler drin:

    Nur weil Du einer Variable (dtBspDaten) einen neuen Wert zuweist, ändert sich nicht der Zustand einer anderen (hier DataContext). Gib den Tabellen mal Namen und baue in den Button Click am Ende ein:

    Console.WriteLine("Tabelle ist: " + (this.DataContext as DataView).Table.TableName);

    Und es kommt der gleiche Name heraus den Du bei GetBspTable verwendest.

    Ergo musst Du  nicht nur die DataTable zuweisen, sondern auch den DataContext neu festlegen.
    Zur Fehlervermeidung sinnvoll: Mache aus der DataTable eine Eigenschaft und baue im Setter eine Zuweisung an den DataContext ein.

    Im übrigen implementiert die DataTable / DataView kein INotifyCollectionChanged, da sie zu "alt" dafür ist. Was aber keine Rolle spielt: Das gleiche Problem würdest Du auch bei einer ObservableCollection bekommen.

    Gruß Elmar

    • Als Antwort markiert perlfred Freitag, 12. Oktober 2012 09:42
    Freitag, 12. Oktober 2012 08:35

Alle Antworten

  • Hi,
    INotifyCollectionChanged signalisiert nur die Änderung der Auflistung, wenn Elemente hinzugefügt oder entfernt worden. Eine Änderung der Inhalte eines Elementes löst kein INotifyCollectionChanged aus. Das müsstest Du bei Bedarf selbst weiterleiten, indem Du an jedes Element einen Ereignishandler für IPropertyChanged hängst. Das setzt aber voraus, dass die Datenobjekte auch INotifyPropertyChanged implementieren.
     
    Wenn Du die Daten in der externen Tabelle änderst, musst Du auch ein Refresh der Inline-Datenbank ausführen. In der externen Datenbank gelöschte Datensätze werden dabei aber nicht berücksichtigt.
     
    --
    Viele Gruesse
    Peter
    Freitag, 12. Oktober 2012 07:23
  • Hallo!

    Ich habe mein Aktualisierungs-Problem mit zwei DataTable-Tabellen in einem ganz kurzen Bsp. dargestellt:

    XAML:

    <Window x:Class="TabelleAktualisieren.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="174" Width="286" Name="wndStamm" Loaded="wndStamm_Loaded" WindowStartupLocation="CenterScreen">
        <Grid>
            <TextBlock Text="{Binding VorName}" />
            <Button Name="btnEditData" Content="Veränder Daten" Click="btnEditData_Click" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,10" />
        </Grid>
    </Window>

    CodeBehind:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    
        DataTable dtBspDaten = new DataTable();     // Zentrale Tabelle
                    
        private void wndStamm_Loaded(object sender, RoutedEventArgs e)
        {
            dtBspDaten = GetBspTable();                     // Beispieldaten erzeugen
            wndStamm.DataContext = dtBspDaten.DefaultView;  // DataContext des Fensters setzen
        }
    
        /// <summary>
        /// Erstellt eine gefüllte Beispiel DataTable
        /// </summary>
        private DataTable GetBspTable()
        {
            DataTable table = new DataTable();
            table.Columns.Add("ID", typeof(int));
            table.Columns.Add("VorName", typeof(string));
            // Inhalt
            table.Rows.Add(1, "Fred");
            table.Rows.Add(2, "Florian");
            return table;
        }
    
        private DataTable GetBspTable2()        // 2. Tabelle
        {
            DataTable table = new DataTable();
            table.Columns.Add("ID", typeof(int));
            table.Columns.Add("VorName", typeof(string));
            // Inhalt
            table.Rows.Add(1, "Peter");
            table.Rows.Add(2, "Max");
            return table;
        }
    
        private void btnEditData_Click(object sender, RoutedEventArgs e)
        {
            // dtBspDaten.Rows[0][1] = "Peter";       // Direkte Änderung funktioniert :-)
            dtBspDaten = GetBspTable2();              // Der zentralen Tabelle neue Daten zuordnen  
            MessageBox.Show("dtBspDaten (Neu): "+(string)dtBspDaten.Rows[0][1]);
        }
    
    }

    Nach einen Klick auf den Button müßte doch Peter stehen!!!

    Fred.


    • Bearbeitet perlfred Freitag, 12. Oktober 2012 07:57 Detailkorrektur
    Freitag, 12. Oktober 2012 07:49
  • Hallo Fred,

    da hast Du einen kleinen Denkfehler drin:

    Nur weil Du einer Variable (dtBspDaten) einen neuen Wert zuweist, ändert sich nicht der Zustand einer anderen (hier DataContext). Gib den Tabellen mal Namen und baue in den Button Click am Ende ein:

    Console.WriteLine("Tabelle ist: " + (this.DataContext as DataView).Table.TableName);

    Und es kommt der gleiche Name heraus den Du bei GetBspTable verwendest.

    Ergo musst Du  nicht nur die DataTable zuweisen, sondern auch den DataContext neu festlegen.
    Zur Fehlervermeidung sinnvoll: Mache aus der DataTable eine Eigenschaft und baue im Setter eine Zuweisung an den DataContext ein.

    Im übrigen implementiert die DataTable / DataView kein INotifyCollectionChanged, da sie zu "alt" dafür ist. Was aber keine Rolle spielt: Das gleiche Problem würdest Du auch bei einer ObservableCollection bekommen.

    Gruß Elmar

    • Als Antwort markiert perlfred Freitag, 12. Oktober 2012 09:42
    Freitag, 12. Oktober 2012 08:35
  • Hallo Peter!

    Danke für deine Antwort!

    Das INotifyCollectionChanged nicht auf Inhaltsänderungen reagiert war mir nicht bewußt. Collection Changed ( und nicht Collection Modify) hätte mich ja wachrütteln müssen, aber ...

    Den Denkfehler hatte ich aber bei der Auswirkung der Zusweisung der geänderten Daten an die bestehende DataTable. Das dadurch nicht gleichzeitig der DataContext geändert wird bzw. das ich den DataContext erneut auf die "gleiche" DataTable setzen muss. Siehe Antwort von Elmar.

    Das gelöschte DS beim Refresh nicht berücksichtigt werden, habe ich auch noch nicht bemekt. Nochmals Danke für diesen praktischen Hinweis.

    Fred.

    Freitag, 12. Oktober 2012 09:42
  • Hallo Elmar!

    Natürlich hast du Recht. Ich wollte aber eben gerade der anderen Variable (DataContext)  keinen neuen Wert zuweisen. Diese verweist ja (davor und danach) auf die zentrale DataTable.

    Aber genau da liegt mein Denkfehler. Es ist nicht die selbe DataTable obwohl sie die gleiche Bezeichnung hat.

    Der Hinweis die DataTable als Eigenschaft zu benutzen ist gut! aber jetzt muss ich mich mit einem anderen Problem auseinandersetzen, dass durch die erneute Zuweisung des DataContext ein anderer DataContext (in einer anderen Ebene) überschrieben wird.

    Vielen! Dank auf jeden Fall für diese Lösung!!

    Fred

    • Bearbeitet perlfred Freitag, 12. Oktober 2012 10:34 Berichtigung
    Freitag, 12. Oktober 2012 10:32