wpf 菜单样式和绑定树形数据

前言

在wpf开发中,经常会使用到Menu和ContentMenu。但是原生的样式比较简陋,对于比较追求界面美好的人来说是十分不友好的。那么,这就涉及到对Menu的样式修改了。与此同时,我们还希望Menu自动Binding到视图数据模型上,根据数据项自动展开MenuItem。接下来就对这些想法做一简单实现。

视图模型

假设我们的菜单项里有描述意图的缩略图和文字需要展示。那么我们需要有名字和存有图片路径的属性。额外的,还需要一个Children集合来存放子项,以形成树形数据。

视图模型Class

public class CommonTreeModel
{
    /// 
    /// 名字
    /// 
    public string Name { get; set; }
    /// 
    /// 图片的路径
    /// 
    public string IconPath { get; set; }
    /// 
    /// 子项
    /// 
    public ObservableCollection Children { get; set; }
}

数据mock

我们使用Bogus进行模拟数据的产生。使用nuget搜索Bogus添加即可。

/// 
/// 菜单项数据集,前端将binding到该属性上
/// 
public ObservableCollection MenuTreeSource { get; set; }

private void InitData()
{
    var general = new Bogus.Faker()
        .RuleFor(t => t.Name, t => t.Commerce.Product())//名字:商业产品
        .RuleFor(t => t.IconPath, t => t.Image.LoremFlickrUrl(32, 32));//图片:使用LoremFlick网站的图片
    var rd = new Random(DateTime.Now.Millisecond);//随机数
    MenuTreeSource = GenerateTreeData(general, rd, 10, 3, 10);
}

private ObservableCollection GenerateTreeData(Faker faker, Random rd, int topCount, int subMin, int subMaxm, int level = 0, int levelLimit = 4)
{
    var list = new ObservableCollection(faker.Generate(level == 0 ? topCount : rd.Next(subMin, subMaxm)));
    level++;
    if (level < levelLimit)
    {
        foreach (var item in list)
        {
            if (rd.Next() % 2 == 0)
            {
                item.Children = GenerateTreeData(faker, rd, topCount, subMin, subMaxm, level, levelLimit);
            }
        }
    }
    return list;
}

到这里,我们生成了最大层级可能为4的一棵树:MenuTreeSource

WPF中的Menu

我们先写前端Menu绑定到数据。


    
        
            
        
    

原始的样式展示效果如下,总共有四级,并且第一级和后三级不一致。

wpf 菜单样式和绑定树形数据_第1张图片

我们只需重写MenuItem的样式,就能够改变菜单的展示效果:


                    
                    
                        
                        
                        
                    
                    
                    

控件Popup用于展示子级菜单项。其中StackPanel上的IsItemsHost="True"保证正确处理子级。

名为MoreLbl的Label控件用于提示是否有子级。这里简略用>>标识一下,读者可以图片Image或者Path控件做一个漂亮的样式。

最终效果如下,一级和次级依然不统一。

统一Menu的一级和次级

为了统一,我们需要对Menu的样式加以调整。最简单的方式是对子项承载容器进行替换,我们用StackPanel控件,并把内容排序设置为垂直方向即可。


    
        
            
        
    
    
        
    

最终效果如下:

wpf 菜单样式和绑定树形数据_第2张图片

WPF中的ContextMenu控件

ContextMenu与Menu不同,他可以作为很多控件的Popup形式的鼠标右键弹出菜单,比如作为ListBox,Label,Grid等的内容菜单都是可以的,我们只需鼠标右键就可以将其弹出。

我们用Label简单举例:


之前的样式都是全局样式,默认会自动使用。效果如下:

能够发现一级的样式稍微有些不一样,我们需要改ContextMenu的样式


简单重写Template即可。

总结

这里只简单介绍如何去重写样式模板来改变菜单展示效果。具体使用中大家需要更好看的效果请自行设计。该wpf项目框架使用dotnet core3.1版本。在farmwork中应该一样。

你可能感兴趣的:(wpf 菜单样式和绑定树形数据)