多层菜单的实现方案(含HierarchicalDataTemplate使用)

50 篇文章 0 订阅
21 篇文章 1 订阅

1、递归

        下面是Winform的递归添加菜单栏数据,数据设置好父子id方便递归使用

在TreeView的控件窗口加载时,调用递归加载菜单

private void LoadTvMenu()
        {
            this.nodeList = objService.GetAllMenu();    // 通过Service得到全部数据

            // 创建一个根节点
            this.tv_MenuList.Nodes.Clear(); // 亲空所有节点
            // 这个是TreeView的节点
            TreeNode rootNode = new TreeNode();
            rootNode.Text = "学员管理系统";
            rootNode.Tag = "0"; // 暂时没什么用
            rootNode.ImageIndex = 0;    // 设置根节点现实的图片
            this.tv_MenuList.Nodes.Add(rootNode);   // 将根节点添加到treeview根节点

            // 基于递归方式添加所有子节点
            CreateChildNode(rootNode, "0");
        }


        private void CreateChildNode(TreeNode parentNode, string preId)
        {
            var nodes = from list in nodeList
                        where list.ParentId.Equals(preId)
                        select list;

            foreach (var item in nodes)
            {
                TreeNode node = new TreeNode();
                node.Text = item.MenuName;
                node.Tag = item.MenuCode;

                // 设置节点图表
                if (item.ParentId == "0")
                {
                    node.ImageIndex = 1;
                }
                else
                {
                    node.ImageIndex = 3;
                }

                parentNode.Nodes.Add(node); // 给父节点添加上这个子节点

                // 递归调用
                CreateChildNode(node, item.MenuId.ToString());
                this.tv_MenuList.Nodes[0].Expand(); // 将一级目录全部展开
                this.tv_MenuList.ExpandAll();
            }
        }

在WPF中也是差不多的可以用递归实现加载TreeView

2、WPF中可以使用HierarchicalDataTemplate非常方便

 创建数据类

public class ListLeagueList : ObservableCollection<League>
{
    List<League> leagues = new List<League>();
    List<Division> divisions = new List<Division>();
    List<Team> teams = new List<Team>();

    public ListLeagueList()
    {
        teams.Add(new Team() { Name = "Team 1" });
        teams.Add(new Team() { Name = "Team 2" });
        teams.Add(new Team() { Name = "Team 3" });
        teams.Add(new Team() { Name = "Team 4" });

        divisions.Add(new Division() { Name = "Division 1", Teams = teams });
        divisions.Add(new Division() { Name = "Division 2", Teams = teams });
        divisions.Add(new Division() { Name = "Division 3", Teams = teams });

        Add(new League() { Name = "League a", Divisions = divisions });
        Add(new League() { Name = "League b", Divisions = divisions });
        Add(new League() { Name = "League c", Divisions = divisions });
    }
}

 view中        设置下一个子集合为ItemsSource

<DockPanel>
    <DockPanel.Resources>
        <local:ListLeagueList x:Key="myList" />
        <HierarchicalDataTemplate DataType="{x:Type models:League}" ItemsSource="{Binding Divisions}">
            <TextBlock Text="{Binding Path=Name}" />
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate DataType="{x:Type models:Division}" ItemsSource="{Binding Teams}">
            <TextBlock Text="{Binding Path=Name}" />
        </HierarchicalDataTemplate>
        <!--  最后一个没有ItemsSource  -->
        <HierarchicalDataTemplate DataType="{x:Type models:Team}">
            <TextBlock Text="{Binding Path=Name}" />
        </HierarchicalDataTemplate>
    </DockPanel.Resources>


    <Menu
        x:Name="menu1"
        Margin="10"
        DockPanel.Dock="Top">
        <MenuItem Header="我的足球联赛" ItemsSource="{Binding Source={StaticResource myList}}" />
    </Menu>

    <TreeView x:Name="treeView1">
        <TreeViewItem Header="我的足球联赛" ItemsSource="{Binding Source={StaticResource myList}}" />
    </TreeView>

</DockPanel>

使用HierarchDataTemplate后可以显示多层的控件都可以使用

-- 这里的ItemsSource是集合,使用其它方式绑定上也是一样的;HierarchicalDataTemplate就是独立于这个集合的,检测到合适就起作用

HierarchicalDataTemplate使用样例2(实现菜单栏):

WPF中:

<TreeView
    Margin="0,10"
    Background="Transparent"
    BorderThickness="0"
    ItemsSource="{Binding Menus}"
    ScrollViewer.VerticalScrollBarVisibility="Auto">
    <TreeView.ItemTemplate>
        <!--  TreeView也有模板,上面是TreeViewItem的模板  -->
        <HierarchicalDataTemplate ItemsSource="{Binding Children}"> <!--这里比较伟大的地方就是绑定的是子类-->
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Name="c1" Width="30" />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <!--  左侧图标  -->
                <TextBlock
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    FontFamily="{StaticResource Iconfont}"
                    FontSize="18"
                    SnapsToDevicePixels="True"
                    Text="{Binding MenuIcon}" />
                <!--  右侧文字  -->
                <TextBlock
                    Grid.Column="1"
                    Margin="5,0,0,0"
                    FontSize="13"
                    Text="{Binding MenuHeader}" />
            </Grid>
            <!--没有就图标都不要显示了-->
            <HierarchicalDataTemplate.Triggers>
                <DataTrigger Binding="{Binding MenuIcon}" Value="{x:Null}">
                    <Setter TargetName="c1" Property="Width" Value="0" />
                </DataTrigger>
            </HierarchicalDataTemplate.Triggers>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

这个页面的ViewModel,通过递归加载菜单

public class TreeMenuViewModel
{
    public List<MenuItemModel> Menus { get; set; } = new List<MenuItemModel>();

    // 列表,没有树形结构
    private List<MenuEntity> origMenMenus = null;
    private readonly IRegionManager _regionManager;

    public TreeMenuViewModel(IRegionManager regionManager)
    {
        this._regionManager = regionManager;    // 要在FillMenus调用前赋值要不然就是null
        // 需要获取菜单数据
        origMenMenus = GlobalEntity.CurrentUserInfo?.Menus; // 这个用户的菜单

        this.FillMenus(Menus, 0);
    }


    /// <summary>
    /// 递归遍历出所有的菜单
    /// </summary>
    /// <param name="menus"></param>
    /// <param name="parentId"></param>
    private void FillMenus(List<MenuItemModel> menus, int parentId)
    {
        var sub = origMenMenus.Where(m => m.ParentId == parentId).OrderBy(m => m.Index);

        if (sub.Count() > 0)
        {
            foreach (var item in sub)
            {
                MenuItemModel mm = new MenuItemModel(_regionManager)
                {
                    MenuHeader = item.MenuHeader,
                    MenuIcon = item.MenuIcon,
                    TargetView = item.TargetView,
                };
                menus.Add(mm);

                // 自己调用自己
                FillMenus(mm.Children = new List<MenuItemModel>(), item.MenuId);
            }
        }
    }


}

Item实体:

public class MenuItemModel : BindableBase
{
    public string MenuIcon { get; set; }
    public string MenuHeader { get; set; }
    public string TargetView { get; set; }

    private bool _isExpanded;

    public bool IsExpanded
    {
        get { return _isExpanded; }
        set { SetProperty(ref _isExpanded, value); }
    }

    public List<MenuItemModel> Children { get; set; }

    // 这个打开是将用户控件注入到MainContentRegion,显示出来
    public ICommand OpenViewCommand
    {
        get => new DelegateCommand(() =>
        {
            if (_regionManager == null)
            {

            }
            else
            {

            }

            if ((this.Children == null || this.Children.Count == 0) &&
                !string.IsNullOrEmpty(this.TargetView))
            {
                // 页面跳转(目前只实现了UserManagementView窗口)
                _regionManager.RequestNavigate("MainContentRegion", this.TargetView);  // 更换区域导航
            }
            else
                this.IsExpanded = !this.IsExpanded; // 点了就更换状态
        });
    }

    IRegionManager _regionManager = null;


    // 构造方法注入区域管理
    public MenuItemModel(IRegionManager regionManager)
    {
        _regionManager = regionManager;
    }
}

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用R实现多层线性回归模型可以使用lme4包和nlme包。lme4包是R语言中常用的估计HLM(多层线性模型)的包之一,而nlme包也可以用于多层线性模型的实现。在学习过程中,可以使用lme4包去复现刘红云老师的案例。具体步骤如下: 1. 首先,需要加载所需的包,包括tidyverse、lme4和nlme。可以使用以下代码加载这些包: ```R library(tidyverse) library(lme4) library(nlme) ``` 2. 接下来,需要准备数据集。根据具体的案例,可以选择合适的数据集,并定义数学模型。 3. 然后,可以根据定义的数学模型进行参数估计。使用lme4包的lmer函数可以拟合多层线性回归模型。例如,可以使用以下代码拟合零模型: ```R model <- lmer(MathAchieve ~ 1 + (1 | MathAchSchool), data = your_data) ``` 其中,MathAchieve是因变量,MathAchSchool是随机效应变量。 4. 进行参数估计后,可以对估计出来的参数进行显著性检验、残差分析和异常点检测等。可以使用summary函数查看模型的统计结果。 5. 最后,可以根据需要确定回归方程进行模型预测。 总结起来,使用R实现多层线性回归模型的步骤包括加载所需的包、准备数据集、定义数学模型、参数估计、统计分析和模型预测。 #### 引用[.reference_title] - *1* *3* [多层线性模型在R上的实现](https://blog.csdn.net/qq_44112435/article/details/124755104)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [R语言使用lm函数构建分层线性回归模型(添加分组变量构建分层线性回归模型)、可视化分组散点图](https://blog.csdn.net/weixin_57242009/article/details/124719026)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值