Wednesday, 2 October 2013

WPF MVVM Case: ItemsControl contains hyperlink and command to update property in ViewModel

WPF MVVM Case: ItemsControl contains hyperlink and command to update
property in ViewModel

I have a case, a little bit more complex but I try to illustrate and do
some modification to show the point in a simple way.
Let's say I have a Window1 as view and a Window1ViewModel as its
viewmodel. I also have a SubMenuViewModel class to represent submenu in
the window. I want to make an ItemsControl in Window1 which contains many
submenus. Every time user clicks one of the submenu, the property
CurrentSubMenu updates to the corresponding submenu. This is the problem,
I can't manage to update the CurrentSubMenu in the Window1ViewModel
SubMenuViewModel :
public class SubMenuViewModel : INPC
{
private string _submenuname;
public string SubMenuName
{
get
{ return _submenuname; }
set
{
_submenuname = value;
RaisePropertyChanged("SubMenuName");
}
}
private string _displayname;
public string DisplayName
{
get
{ return _displayname; }
set
{
_displayname = value;
RaisePropertyChanged("DisplayName");
}
}
// Command for Hyperlink in ItemsControl //
private RelayCommand _commandSubmenu;
public RelayCommand CommandSubMenu
{
get
{ return _commandSubmenu; }
set
{
_commandSubmenu = value;
RaisePropertyChanged("CommandSubMenu");
}
}
// end of command
public SubMenuViewModel(string Submenu_name, string Display_name)
{
_submenuname = Submenu_name;
_displayname = Display_name;
}
}
Window1 :
<Window x:Class="SomeProject.Window1"
xmlns:vm="clr-namespace:SomeProject.ViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="This is Some Project" WindowState="Maximized">
<Window.DataContext>
<vm:Window1ViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Name="SubMenuPanelBorder"
Grid.Column="0"
Grid.Row="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="15 0 15 0"
BorderThickness="2"
BorderBrush="Black"
Padding="10 10">
<HeaderedContentControl Content="{Binding Path=SubMenus}"
Header="Panel Submenu :">
<HeaderedContentControl.ContentTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding}"
Foreground="White" Background="Transparent"
Margin="0 15">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock>
<Hyperlink Command="{Binding
Path=CommandSubMenu}">
<TextBlock Margin="0 5"
Text="{Binding
Path=DisplayName}"/>
</Hyperlink>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</HeaderedContentControl.ContentTemplate>
</HeaderedContentControl>
</Border>
.......
.......
</Grid>
</Window>
Window1ViewModel :
class Window1ViewModel : INPC
{
private List<SubMenuViewModel> _submenus;
public List<SubMenuViewModel> SubMenus
{
get
{ return _submenus; }
set
{
_submenus = value;
RaisePropertyChanged("SubMenus");
}
}
private SubMenuViewModel _currentSubMenu;
public SubMenuViewModel CurrentSubMenu
{
get
{ return _currentSubMenu; }
set
{
_currentSubMenu = value;
RaisePropertyChanged("CurrentSubMenu");
}
}
public Window1ViewModel()
{
SubMenus = MenuDefinition.GetSubMenus();
/***
Set the SubMenus's command to update the CurrentSubMenu,
and == HERE IS WHERE I GOT LOST ==.
The CurrentSubMenu is always point to the last submenu in the
loop.
By the way, the reason I use loop is because the submenu in
the Menu definition sometimes changed and there are many
number of submenus there, and there are some other reasons (I
use Menu-submenu mechanism, but it's not essential to show it
here because it's not the main point I want to show). So,
finally I use loop instead of specifying each command one by
one.
***/
foreach(SubMenuViewModel submenu in SubMenus){
submenu.CommandSubMenu=new
RelayCommand(()=>clickedSubMenu(submenu.SubMenuName));
}
}
public void clickedSubMenu(string submenu_name)
{
CurrentSubMenu = SubMenus.Find(sub => sub.SubMenuName ==
submenu_name);
}
}
MenuDefinition :
public static List<SubMenuViewModel> GetSubMenus()
{
return new List<SubMenuViewModel>
{
new SubMenuViewModel("overview_product", "Overview
Products"),
new SubMenuViewModel("search_product","Search
Products"),
new SubMenuViewModel("update_product","Update Data
Products"),
new SubMenuViewModel("order_product","Order
Products"),
new SubMenuViewModel("supplier_product","Products
Supplier"),
.................
.................
.................
};
}
}

No comments:

Post a Comment