Verfasst von: bletra | 7. Mai 2011

WPF: Von Spaghetticode zu MVVM – Teil 2 von 9

In dieser Artikelserie möchte ich eine einfache Applikation, in eine testbare Applikation nach dem MVVM-Pattern umwandeln:

  1. Beispielapplikation mit Spaghetticode
  2. Refactoring 1: Model
  3. MVC, MVP, Presentation Model
  4. MVVM
  5. ICommand
  6. Binding
  7. Refactoring 2: ViewModel
  8. Refactoring 3: View
  9. Zusammenfassung

Im ersten Artikel dieser Serie habe ich die zu verbessernde Applikation vorgestellt und erläutert, warum ein Refactoring notwendig ist. In diesem Artikel geht es um die Extraktion der Kernfunktionalität, die wir in einer Klasse FeedModel implementieren.

Refactoring 1: Model

Sie können hierzu mit einem neuen Projekt starten oder das vorhandene Projekt umgestalten (refactor). Erzeugen Sie eine neue Klasse (FeedModel) und verschieben Sie dorthin die Methoden LoadFeeds, die Kerninhalte der Methoden btnSave_Click und btnAddFeed_Click sowie den privaten Member _feeds. Im Konstruktor der Klasse rufen Sie die Methode LoadFeeds auf. Dabei verbessern Sie auch das Coding der Methoden und erhalten nun:

//Refactoring 1: Extraktion der Kernfunktionalität
public class FeedModel
{
    private Dictionary _feeds;
    private const string REPOSITORY_FILENAME = "feeds.dat";
    public FeedModel()
    {
        LoadFeeds();
    }
    public void SaveFeeds()
    {
        using (FileStream writeStream = new FileStream(REPOSITORY_FILENAME, FileMode.Create))
        {
            BinaryFormatter serializer = new BinaryFormatter();
            serializer.Serialize(writeStream, _feeds);
            writeStream.Close();
        }
    }
    public void AddFeed(string address)
    {
        Uri feedUri;
        Uri.TryCreate(address, UriKind.Absolute, out feedUri);
        if (feedUri == null)
            throw new UriFormatException("Error: The given address is no proper URI.");
        WebClient request = new WebClient();
        string xml = request.DownloadString(feedUri);
        if (xml.Length == 0)
            throw new XmlException("Error: The given address does not belong to a proper feed.");
        StringReader stringReader = new StringReader(xml);
        XmlReader reader = XmlReader.Create(stringReader);
        SyndicationFeed feed = SyndicationFeed.Load(reader);
        if (feed == null)
            throw new XmlException("Error: The given address does not belong to a proper feed.");
        if (_feeds.ContainsKey(feed.Title.Text))
            throw new DuplicateNameException("Error: The address is already listed.");
        _feeds.Add(feed.Title.Text, address);
    }

    public Dictionary Feeds
    {
        get { return _feeds; }
    }

    private void LoadFeeds()
    {
        if (!File.Exists(REPOSITORY_FILENAME))
        {
            _feeds = new Dictionary();
            return;
        }
        using (FileStream readStream = new FileStream(REPOSITORY_FILENAME, FileMode.Open))
        {
            BinaryFormatter serializer = new BinaryFormatter();
            _feeds = serializer.Deserialize(readStream) as Dictionary;
            readStream.Close();
        }
    }
}

Sie können nun nach InitializeComponent in MainWindow eine Instanz Ihres Models erzeugen, als privaten Member (_model) verfügbar machen und die Listbox mit lbFeeds.ItemsSource = _model.Feeds; an das Model binden. Bei btnAddFeed_Click etc. rufen Sie nun die entsprechenden Methoden des Models auf, z.B.:

private void btnAddFeed_Click(object sender, RoutedEventArgs e)
{
    string msg = "";
    try
    {
        _model.AddFeed(txtFeedAddress.Text);
        msg = "Added feed successfully.";
        txtFeedAddress.Text = string.Empty;
        lbFeeds.Items.Refresh();
    }
    catch(Exception ex)
    {
        msg = ex.Message;
    }
    MessageBox.Show(msg);
    this.Cursor = Cursors.Arrow;
}

Anstelle der MessageBox können Sie natürlich auch eine StatusBar verwenden und die Nachricht dort anzeigen.

Dieses Model können Sie auch in einer Asp.Net-Applikation analog verwenden und automatische Tests für die Methoden des Models schreiben.

WPF bieten noch weitere Möglichkeiten, die Applikation zu überarbeiten. Wir können auch die Logik der View kapseln. Beispielsweise soll der Add-Button disabled sein, wenn das Feld der Adresse leer ist. Die Modularisierung dieser View-Logik ermöglicht das MVVM-Pattern, das ich im übernächsten Artikel vorstellen möchte. MVVM basiert auf bekannte Architekturmuster auf, diese führe ich im nächsten Artikel ein.

Advertisements

Responses

  1. […] Refactoring 1: Model […]


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: