我正在与一个关于LoB应用程序的团队合作.我们希望有一个动态Menu控件,它根据登录的用户配置文件创建菜单.在以前的开发方案(即ASP.NET)中,我们使用迭代描述集合和MenuItem动态生成的数据.在MVVM中我该怎么做?我可以将XAML视图与描述菜单元素的ViewModel分开吗?
解:
通过评论员的输入,我能够Menu动态绑定ViewModel中的数据.这篇文章也很有帮助.
XAML:
<HierarchicalDataTemplate DataType="{x:Type self:Menu}" ItemsSource="{Binding Path=Children, UpdateSourceTrigger=PropertyChanged}">
<ContentPresenter Content="{Binding Path=MenuText}" RecognizesAccessKey="True"/>
</HierarchicalDataTemplate>
[...]
<Menu Height="21" Margin="0" Name="mainMenu" VerticalAlignment="Top" HorizontalAlignment="Stretch"
ItemsSource="{Binding Path=MenuItems, UpdateSourceTrigger=PropertyChanged}" ItemContainerStyle="{StaticResource TopMenuItems}">
<Menu.Background>
<ImageBrush ImageSource="/Wpf.Modules;component/Images/MenuBg.jpg" />
</Menu.Background>
</Menu>
Run Code Online (Sandbox Code Playgroud)
Menu 数据类:
public class Menu : ViewModelBase
{
public Menu()
{
IsEnabled = true;
Children = new List<Menu>();
}
#region [ Menu Properties ]
private bool _isEnabled;
private string _menuText;
private ICommand _command;
private IList<Menu> _children;
public string MenuText
{
get { return _menuText; }
set
{
_menuText = value;
base.OnPropertyChanged("MenuText");
}
}
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
base.OnPropertyChanged("IsEnabled");
}
}
public ICommand Command
{
get { return _command; }
set
{
_command = value;
base.OnPropertyChanged("Command");
}
}
public IList<Menu> Children
{
get { return _children; }
set
{
_children = value;
}
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ann 16
尝试这样的事情:
public class MenuItemViewModel
{
public MenuItemViewModel()
{
this.MenuItems = new List<MenuItemViewModel>();
}
public string Text { get; set; }
public IList<MenuItemViewModel> MenuItems { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
假设您的DataContext有一个名为MenuItems的属性,它是MenuItemViewModel的列表.这样的事情应该有用,然后:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type self:MenuItemViewModel}"
ItemsSource="{Binding Path=MenuItems}">
<ContentPresenter Content="{Binding Path=Text}" />
</HierarchicalDataTemplate>
</Window.Resources>
<DockPanel>
<Menu DockPanel.Dock="Top" ItemsSource="{Binding Path=MenuItems}" />
<Grid />
</DockPanel>
</Window>
Run Code Online (Sandbox Code Playgroud)
Ada*_*nda 14
这应该可以让你到达目的地
<UserControl x:Class="WindowsUI.Views.Default.MenuView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ViewModels="clr-namespace:WindowsUI.ViewModels"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Path=DisplayName}"/>
<Setter Property="Command" Value="{Binding Path=Command}"/>
</Style>
<HierarchicalDataTemplate
DataType="{x:Type ViewModels:MenuItemViewModel}"
ItemsSource="{Binding Path=Items}">
</HierarchicalDataTemplate>
</UserControl.Resources>
<Menu DockPanel.Dock="Top" ItemsSource="{Binding Path=Items}"/>
Run Code Online (Sandbox Code Playgroud)
请注意,在我的示例中,我的菜单Item有一个名为Command的ICommand类型的属性.
该解决方案不需要代码中的任何代码,这使得它更简单的解决方案.
<Menu>
<MenuItem ItemsSource="{Binding Path=ChildMenuItems}" Header="{Binding Path=Header}">
<MenuItem.Resources>
<HierarchicalDataTemplate DataType="{x:Type vm:MenuItemViewModel}" ItemsSource="{Binding ChildMenuItems}">
<MenuItem Header="{Binding Path=Header}" Command="{Binding Path=Command}"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type vm:SeparatorViewModel}">
<Separator>
<Separator.Template>
<ControlTemplate>
<Line X1="0" X2="1" Stroke="Black" StrokeThickness="1" Stretch="Fill"/>
</ControlTemplate>
</Separator.Template>
</Separator>
</DataTemplate>
</MenuItem.Resources>
</MenuItem>
</Menu>
Run Code Online (Sandbox Code Playgroud)
MenuItem表示为:
public class MenuItemViewModel : BaseViewModel
{
/// <summary>
/// Initializes a new instance of the <see cref="MenuItemViewModel"/> class.
/// </summary>
/// <param name="parentViewModel">The parent view model.</param>
public MenuItemViewModel(MenuItemViewModel parentViewModel)
{
ParentViewModel = parentViewModel;
_childMenuItems = new ObservableCollection<MenuItemViewModel>();
}
private ObservableCollection<MenuItemViewModel> _childMenuItems;
/// <summary>
/// Gets the child menu items.
/// </summary>
/// <value>The child menu items.</value>
public ObservableCollection<MenuItemViewModel> ChildMenuItems
{
get
{
return _childMenuItems;
}
}
private string _header;
/// <summary>
/// Gets or sets the header.
/// </summary>
/// <value>The header.</value>
public string Header
{
get
{
return _header;
}
set
{
_header = value; NotifyOnPropertyChanged("Header");
}
}
/// <summary>
/// Gets or sets the parent view model.
/// </summary>
/// <value>The parent view model.</value>
public MenuItemViewModel ParentViewModel { get; set; }
public virtual void LoadChildMenuItems()
{
}
}
Run Code Online (Sandbox Code Playgroud)
具体的MenuItem可以直接实例化,也可以通过继承创建自己的SubType.
| 归档时间: |
|
| 查看次数: |
40941 次 |
| 最近记录: |