Folgende Aufgabenstellung:

Eine XML soll die Daten für ein Menü bereitstellen. Das ganze ohne CodeBehind und unter MVVM.

Die XML sieht folgendermaßen aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<TopNavigationItems>
  <NavigationItem>
    <MenuImage>new.png</MenuImage>
    <MenuName>Neu</MenuName>
  </NavigationItem>
  <NavigationItem>
    <MenuImage>preferences.png</MenuImage>
    <MenuName>Tools</MenuName>
  </NavigationItem>
  <NavigationItem>
    <MenuImage>search.png</MenuImage>
    <MenuName>Suche</MenuName>
  </NavigationItem>
</TopNavigationItems>

Dazu habe ich als Model eine Klasse TopNavigationMenuItem erstellt mit lediglich zwei Propertys:

1
2
3
4
5
  public class TopNavigationMenuItem
  {
    public String MenuName { get; set; }  
    public String MenuImage { get; set; }  
  }

Anschliessend hab ich eine weitere Klasse in Models erstellt welche eine Methode enthält, die eine Liste von TopNavigationMenuItem zurück gibt. Hier benutze ich LINQ2XML um mir die Knoten heraus zu selektieren:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
 
public class TopNavigationMenuItems
  {
    private static TopNavigationMenuItem navigationItem;
    private static List<TopNavigationMenuItem> topNavigationMenuItemList = new List<TopNavigationMenuItem>();
 
    public static List<TopNavigationMenuItem> getTopNavigationItems()
    {
      var xmlPath = Path.GetDirectoryName(@"\Pfad\zur\TopNavigationItems.xml";
      var NavigationItems = XElement.Load(xmlPath);
 
      foreach (var item in NavigationItems.Elements())
      {
        navigationItem = new TopNavigationMenuItem();
        navigationItem.MenuName = (string)item .Element("MenuName");
        navigationItem.MenuImage = (string)item .Element("MenuImage");
        topNavigationMenuItemList.Add(navigationItem); 
      }
      return topNavigationMenuItemList;
    }
  }

Im ViewModel habe ich dann das ViewModelProperty TopMenuItems erstellt welche die Daten für die View in eine ObservableCollection bereitstellen soll.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    #region ViewModelProperty: TopMenuItems
    private ObservableCollection<TopNavigationMenuItem> _topNavigationMenuItem = new ObservableCollection<TopNavigationMenuItem>();
    public ObservableCollection<TopNavigationMenuItem> TopMenuItems
    {
      get
      {
        return _topNavigationMenuItem;
      }
 
      set
      {
        _topNavigationMenuItem = value;
        OnPropertyChanged("TopMenuItems");
      }
    }
    #endregion

im Konstruktor von dem ViewModel wird dann die Liste aus dem Model der ObservableCollection zugewiesen:

1
2
3
4
    public TopMenuMainViewModel()
    {
      TopNavigationMenuItems.getTopNavigationItems().ForEach(x => TopMenuItems.Add(x));
    }

Und hier kommt der der Lamda Ausdruck zum Einsatz, den wir schon einmal Beachtung geschenkt haben.

Zum Schluss dann in der View noch die Daten an die ObservableCollection binden und in einem DataTemplate aufbereiten:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<UserControl ...
    <UserControl.Resources>
        <DataTemplate x:Key="MenuItemStyle">
            <StackPanel Orientation="Horizontal">
                <Image Source="{Binding MenuImage}" Width="16" Height="16" Margin="0 0 5 0"  />
                <TextBlock Text="{Binding MenuName}" />
            </StackPanel>
        </DataTemplate>
    </UserControl.Resources>
 
    <Grid>
        <Menu Grid.Column="1"
              VerticalAlignment="Top" 
              HorizontalAlignment="Left" 
              Background="Transparent" ItemsSource="{Binding TopMenuItems}" ItemTemplate="{StaticResource MenuItemStyle}" />
</UserControl>

Fertig : )

MenuItems aus XML auslesen und binden – WPF / MVVM
Markiert in: