Verfasst von: bletra | 5. Juli 2011

WPF: DataSet und DataGrid

Nachdem ich mit mit WPF und MVVM beschäftigt habe, stellte sich mir die Frage, wie ein ViewModel mit einem DataGrid kommuniziert. Zunächst experimentierte ich mit INotifyPropertyChanged. Doch hat folgende Überlegung gewonnen, die auch noch leichter zu implementieren ist: Es sollen nicht alle Änderungen sofort in die Datenbank weggeschrieben werden, denn das ist doch gerade der Clou eines verbindungslosen Datenobjekts (DataSet), die Benutzer sollen alle Änderungen in Ruhe durchführen und auf Knopfdruck werden diese auf einen Schlag in die Datenbank geschrieben.

Jetzt musste ich nur noch rausfinden, dass als zu bindendes Objekt DataView deutlich besser geeignet ist, als das DataSet selbst und folgender Code läuft wunderbar:

//MainWindow.cs
InitializeComponent();
DataContext = new DBViewModel();

//DBViewModel.cs
class DBViewModel
{
  private const string CONN_STRING = @"Server=localhost;Database=SQLLectureDemo;Uid=demo;Pwd=geheim;";
  private const string SELECT_SQL = "SELECT Id, Name, Birthday, Matrikel FROM Student";
  private ICommand _saveCmd;
  private DataSet _students;

  public DBViewModel()
  {
    _students = ReadDataIntoDataSet();
    _saveCmd = new DelegateCommand((param) => SaveDataSetChangesToDb());
  }

  public DataView Students
  {
    get { return _students.Tables[0].DefaultView; }
  }

  public ICommand SaveCmd
  {
    get { return _saveCmd; }
  }

  private static DataSet ReadDataIntoDataSet()
  {
    DataSet myDataSet;
    using (MySqlConnection conn = new MySqlConnection(CONN_STRING))
    {
      conn.Open();
      MySqlCommand cmd = new MySqlCommand(SELECT_SQL, conn); //fetches primary key, as needed by commandbuilder
      MySqlDataAdapter myMySqlDataAdapter = new MySqlDataAdapter(cmd);
      myDataSet = new DataSet(); //disconnected storage
      myMySqlDataAdapter.Fill(myDataSet, "Student");
      myMySqlDataAdapter.Dispose(); //not needed any longer!
      conn.Close();
    }
    return myDataSet;
  }

  private void SaveDataSetChangesToDb()
  {
    using (MySqlConnection conn = new MySqlConnection(CONN_STRING))
    {
      conn.Open();
      MySqlCommand cmd = new MySqlCommand(SELECT_SQL, conn);
      MySqlDataAdapter da = new MySqlDataAdapter(cmd); //select cmd as used to fill the dataset!
      MySqlCommandBuilder builder = new MySqlCommandBuilder(da); //needed to build the commands
      da.Update(_students, "Student");
      conn.Close();
    }
  }
}

Mit MainWindow.xaml:

<DataGrid  Height ="250" HorizontalAlignment="Stretch" Margin="0"  AutoGenerateColumns="True"  ItemsSource="{Binding Path=Students}"  Name="dataGrid"  AlternatingRowBackground="#FF1ACE1A" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible" />
<Button Name="btnSave" Content="write changes to database" Command="{Binding Path=SaveCmd}" />

Dabei verwende ich die in Artikel „WPF: Von Spaghetticode zu MVVM – Teil 5 von 9“ eingeführte Klasse DelegateCommand.

Das Beispiel greift auf eine MySql-Datenbank zu. Wenn Sie den ConnectionString anpassen und bei den DB-Klassen anstelle des Prefixes MySql nur das Prefix Sql verwenden, so funktioniert das Beispiel auch für den Sql-Server von Microsoft.

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

Kategorien

%d Bloggern gefällt das: