WPF-菜单和Tab控件

WPF-菜单和Tab控件

因为菜单和Tab控件一起用,所以就拿出来一块写

Tab控件

定义一个名为ViewItem类,定义Tab的属性

/// <summary>
     /// tab  item
     /// </summary> 
     public class ViewItem
     {
         /// <summary>
         /// 标题
         /// </summary>
         public string Header
         {
             get;
             set;
         }
 
         /// <summary>
         /// 主键名称
         /// </summary>
         public string KeyName
         {
             get;
             set;
         }
 
         /// <summary>
         /// the show Control
         /// </summary>
         public object ViewControl
         {
             get;
             set;
         }
     }

TabControl用的是Dev的控件,所以先要引用三个Dev的DLL,分别是DevExpress.Xpf.Core,DevExpress,Xpf.Docking,DevExpress.Xpf.Layout.Core。

新建一个UserControl,命名为MenuControl,在主窗体的Window中需要添加一下引用

xmlns:dxd="http://schemas.devexpress.com/winfx/2008/xaml/docking"         xmlns:c="clr-namespace:RemindWin"
         xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
         Name="MainView_View"

其中,c引用的是MenuControl所在的文件夹,因为要用到MenuControl,所以需要引用MenuControl所在的文件夹。并为窗体命名为“MainView_View”(后面用到)。

定义一个DockPanel,在其的顶端设置菜单栏,内容放TabControl,也可以在下面放FootBar,这里省略,主窗体代码如下:

<Grid x:Name="MainView">
         <DockPanel LastChildFill="True">
             <c:MenuControl DockPanel.Dock="Top" HorizontalAlignment="Left"/>
             <dxd:DockLayoutManager x:Name="dockManager" UseLayoutRounding="True" AllowCustomization="False">
                 <dxd:LayoutGroup Orientation="Vertical" >
                     <dxd:DocumentGroup Name="documentContainer" 
                                    SelectedTabIndex="{Binding SelectedTabIndex,Mode=TwoWay}"
                                    ItemsSource="{Binding ItemList}"
                                    DestroyOnClosingChildren="False" 
                                    Background="Azure"
                                    ClosePageButtonShowMode="InActiveTabPageAndTabControlHeader">
                         <dxd:DocumentGroup.ItemStyle>
                             <Style TargetType="dxd:DocumentPanel">
                                 <Setter Property="CloseCommand" Value="{Binding DataContext.CloseCommand,ElementName=MainView}" />
                                 <Setter Property="Caption" Value="{Binding Header}"></Setter>
                                 <Setter Property="AllowFloat" Value="False"></Setter>
                                 <Setter Property="AllowMaximize" Value="False"></Setter>
                             </Style>
                         </dxd:DocumentGroup.ItemStyle>
                         <dxd:DocumentGroup.ItemContentTemplate>
                             <DataTemplate>
                                 <ContentControl Content="{Binding ViewControl}"></ContentControl>
                             </DataTemplate>
                         </dxd:DocumentGroup.ItemContentTemplate>
                     </dxd:DocumentGroup>
                 </dxd:LayoutGroup>
             </dxd:DockLayoutManager>
         </DockPanel>
     </Grid>

binding了Model中的ItemList,这是Tab集合,SelectedTabIndex是所选Tab的索引,为Int型,每个Tab有一个Close事件,Binding后台代码中的CloseCommand事件,属性Caption,banding了ViewItem中的Header,每个Tab的内容ContentControl绑定了ViewItem中的ViewControl,其中需要注意Grid的Name与<Setter>里面的元素一致。

添加主窗体的ViewModel,命名MainViewModel,定义ItemList和SelectedTabIndex(引用了SimpleMvvmToolkit)

<UserControl.Resources>
         <HierarchicalDataTemplate x:Key="ItemTemplate"
                                   ItemsSource="{Binding Childrens}">
             <StackPanel Orientation="Horizontal"  VerticalAlignment="Center">
                 <TextBlock Text="{Binding Header}"
                        IsEnabled="{Binding IsEnabled}"  VerticalAlignment="Center"/>
             </StackPanel>
         </HierarchicalDataTemplate>
         <ControlTemplate x:Key="MenuSeparatorTemplate">
             <Separator />
         </ControlTemplate>
     </UserControl.Resources>
 
     <Menu DockPanel.Dock="Top"
           VerticalAlignment="Top"
           ItemsSource="{Binding MenuList}"
           ItemTemplate="{StaticResource ItemTemplate}">
 
         <!-- 菜单背景色-->
         <Menu.Background>
             <LinearGradientBrush StartPoint="0,0" EndPoint="0,1.5">
                 <GradientStop Color="#f2f2f2" Offset="0.5"/>
                 <GradientStop Color="#F8F9FB" Offset="01"/>
             </LinearGradientBrush>
         </Menu.Background>
         <Menu.ItemContainerStyle>
             <Style TargetType="MenuItem">
                 <Setter Property="IsEnabled"
                         Value="{Binding IsEnabled}" />
                 <Setter Property="Command"
                         Value="{Binding SelectedCommand}" />
                 <Setter Property="CommandParameter"
                         Value="{Binding Header}" />
                 <Setter Property="FontSize" Value="14"/>
                
                 <Style.Triggers>
                     <DataTrigger Binding="{Binding }"
                                  Value="{x:Null}">
                         <Setter Property="Template"
                                 Value="{StaticResource MenuSeparatorTemplate}" />
                     </DataTrigger>
                 </Style.Triggers>
 
             </Style>
         </Menu.ItemContainerStyle>
     </Menu>

View Code

定义菜单的ViewModel,名为MenuControlModel,定义属性

#region Properties
 
         private List<MenuItem> m_MainMenus = new List<MenuItem>();
         public List<MenuItem> MenuList
         {
             get
             {
                 return m_MainMenus;
             }
             set
             {
                 m_MainMenus = value;
                 NotifyPropertyChanged(x => x.MenuList);
             }
         }
 
         #endregion

定义递归设置所有菜单的命令

/// <summary>
         /// 递归设置所有菜单的命令
         /// </summary>
         /// <param name="Menus"></param>
         void SetMenuCommand(List<MenuItem> Menus)
         {
             foreach (var item in Menus)
             {
                 item.SelectedCommand = new DelegateCommand<string>(OpenMenu);
                 if (item.Childrens.Count > 0) SetMenuCommand(item.Childrens);
             }
         }

定义点击菜单Item时执行的方法,其中第一个判断是找到主窗体,再进行操作,如果菜单的Name中包含“测试”两个字符,则使用第一个添加Tab的方法,否则,用第二种。Control_Test和TestModel分别是UserControl和其ViewModel。

/// <summary>
         /// 打开方法
         /// </summary>
         /// <param name="MenuName"></param>
         private void OpenMenu(string MenuName)
         {
             foreach (System.Windows.Window win in System.Windows.Application.Current.Windows)
             {
                 if (win.Name == "MainView_View")
                 {
                     if (MenuName.Contains("测试"))
                     {
                         (win.DataContext as MainViewModel).OpenNewItem<UserControls.Control_Test, UserControls.TestModel>(MenuName, MenuName);
                     }
                     else
                     {
                         UserControls.TestModelSec m = new UserControls.TestModelSec(MenuName);
                         (win.DataContext as MainViewModel).OpenNewItemPara<UserControls.Control_Test>(MenuName, MenuName, m);
                     }
                     break;
                 }
             }
         }

初始化菜单,在“主菜单”中有四个子菜单,其中“操作”的子菜单中还有子菜单

private void LoadMenuData()
         {
             MenuItem mainMenu = new MenuItem("主菜单");
             MenuItem projectMenu = new MenuItem("项目");
             MenuItem toolMenu = new MenuItem("工具");
             MenuItem otherMenu = new MenuItem("其他");
             MenuItem helpMenu = new MenuItem("帮助");
 
             mainMenu.Childrens.Add(new MenuItem("打开"));
             mainMenu.Childrens.Add(new MenuItem("新建"));
 
             MenuItem operateMenu = new MenuItem("操作");
 
 
             MenuItem saveMenu = new MenuItem("保存");
             MenuItem deleteMenu = new MenuItem("删除");
             MenuItem readMenu = new MenuItem("读取");
             operateMenu.Childrens.Add(saveMenu);
             operateMenu.Childrens.Add(deleteMenu);
             operateMenu.Childrens.Add(readMenu);
 
             mainMenu.Childrens.Add(operateMenu);
 
             mainMenu.Childrens.Add(new MenuItem("测试三"));
 
             helpMenu.Childrens.Add(new MenuItem("测试一"));
             helpMenu.Childrens.Add(new MenuItem("测试二"));
             helpMenu.Childrens.Add(new MenuItem("测试三"));
 
             MenuList.Add(mainMenu);
             MenuList.Add(projectMenu);
             MenuList.Add(toolMenu);
             MenuList.Add(otherMenu);
             MenuList.Add(helpMenu);
 
             SetMenuCommand(MenuList);
         }

在构造中,执行初始化菜单的方法

public MenuControlModel()
         {
             LoadMenuData();
         }

结束

Tab每项的内容必须为UserControl,UserControl无需与Model进行banding。测试的UserControl和其Model没有写,只是一个简单的例子~

发表评论