原文:Prism for WPF 搭建一个简单的模块化开发框架(三) 给TreeView加样式做成菜单

昨天晚上把TreeView的样式做了一下,今天给TreeView绑了数据,实现了切换页面功能

上代码把,样式代码

<Style  x:Key="MenuTreeViewItem" TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="MinHeight" Value="40" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Background" Value="{DynamicResource Sys.TreeViewItem.BackgroundBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource Sys.TreeViewItem.BorderBrush}" />
<Setter Property="BorderThickness" Value="0,0,0,1" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Margin" Value="0" />
<Setter Property="FontSize" Value="20"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<StackPanel>
<Border x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"
MinHeight="{TemplateBinding MinHeight}" UseLayoutRounding="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<Grid Margin="{TemplateBinding Margin}" VerticalAlignment="Stretch" >
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="18" Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="21"/>
</Grid.ColumnDefinitions>
<!--图标Text="" -->
<TextBlock x:Name="ItemIcon" Text="{Binding itemIcon}" Foreground="{TemplateBinding Foreground}" FontSize="13" Margin="4" Height="13" VerticalAlignment="Center" Style="{DynamicResource FIcon}"/>
<!--展开收缩按钮-->
<ToggleButton x:Name="ExpanderBtn" Grid.Column="2"
IsChecked="{Binding Path=IsExpanded, RelativeSource={x:Static RelativeSource.TemplatedParent}, Mode=TwoWay}"
ClickMode="Press" >
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<Border>
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</ControlTemplate>
</ToggleButton.Template>
<ToggleButton.Content>
<TextBlock x:Name="ExpanderIcon" Foreground="{TemplateBinding Foreground}" FontSize="13" Margin="4" Height="15" VerticalAlignment="Center" Text="" Style="{DynamicResource FIcon}"/>
</ToggleButton.Content>
</ToggleButton>
<!--内容-->
<ContentPresenter x:Name="PART_Header" Grid.Column="1" ContentSource="Header"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Grid>
</Border>
<ItemsPresenter Margin="5,0,0,0" x:Name="ItemsHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="False">
<Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="IsExpanded" Value="True">
<Setter TargetName="ExpanderIcon" Property="Text" Value="" />
</Trigger>
<Trigger Property="HasItems" Value="False">
<Setter TargetName="ExpanderIcon" Property="Visibility" Value="Hidden" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource Sys.TreeViewItem.MouseOver.BackgroundBrush}" />
<Setter Property="Foreground" Value="{DynamicResource Sys.TreeViewItem.MouseOver.Foreground}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{DynamicResource Sys.TreeViewItem.MouseOver.BackgroundBrush}" />
<Setter Property="Foreground" Value="{DynamicResource Sys.TreeViewItem.MouseOver.Foreground}" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True" />
<Condition Property="Selector.IsSelectionActive" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="{DynamicResource Sys.TreeViewItem.MouseOver.BackgroundBrush}" />
<Setter Property="Foreground" Value="{DynamicResource Sys.TreeViewItem.MouseOver.Foreground}" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <!--TreeView样式-->
<Style x:Key="MenuTreeView" TargetType="{x:Type TreeView}">
<Setter Property="ScrollViewer.CanContentScroll" Value="True" />
<Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"></Setter>
<Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="Background" Value="{DynamicResource Sys.TreeView.BackgroundBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource Sys.TreeView.BorderBrush}"/>
<Setter Property="ItemContainerStyle" Value="{StaticResource MenuTreeViewItem}"></Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True" Margin="0"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>

这里样式就把之前的每个item显示【折叠按钮】、【文本】

改为了显示【图标】、【文本】、【折叠按钮】

出来的效果是这样的,减小了父子两级的缩进,因为父子两级都是相同的样式背景色,并没有把缩进完全去掉

做了个Border做视觉上的分割

下面实现数据绑定

实现了INotifyPropertyChanged接口,一不小心就用上了传说中的MVVM模式?

Model代码

public class MenuViewModel : INotifyPropertyChanged
{
private ObservableCollection<ItemTreeData> itemTreeDataList = new ObservableCollection<ItemTreeData>();
public ObservableCollection<ItemTreeData> ItemTreeDataList
{
get { return itemTreeDataList; }
set
{
itemTreeDataList = value;
NotifyPropertyChanged("ItemTreeDataList");
}
} public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(String propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
} public class ItemTreeData // 自定义Item的树形结构
{
public int itemId { get; set; } // ID
public string itemName { get; set; } // 名称
public string itemView { get; set; }
public string itemRegion { get; set; }
public string itemIcon { get; set; } // private ObservableCollection<ItemTreeData> _children = new ObservableCollection<ItemTreeData>();
public ObservableCollection<ItemTreeData> Children
{ // 树形结构的下一级列表
get
{
return _children;
}
set
{
_children = value;
}
} public bool IsExpanded { get; set; } // 节点是否展开
public bool IsSelected { get; set; } // 节点是否选中
}

组装数据是在个模块的IModule接口下做的,先随意写点数据,itemName就是菜单的显示文本,itemView是要导航的页面,

如果又需要,可以做参数的属性,Prism的导航也是支持传参的

public void Initialize()
{
ObservableCollection<ItemTreeData> chi = new ObservableCollection<ItemTreeData>();
chi.Add(new ItemTreeData() { itemId = 1, itemName = "Map1", itemIcon = "\xe63c", itemRegion = RegionNames.Map, itemView = "View1" });
chi.Add(new ItemTreeData() { itemId = 1, itemName = "Map2", itemIcon = "\xe63c", itemRegion = RegionNames.Map, itemView = "View2" });
chi.Add(new ItemTreeData() { itemId = 1, itemName = "Map3", itemIcon = "\xe63c" });
chi.Add(new ItemTreeData() { itemId = 1, itemName = "Map4", itemIcon = "\xe63c" });
chi.Add(new ItemTreeData() { itemId = 1, itemName = "Map5", itemIcon = "\xe63c" });
MenuViewModel vm = new MenuViewModel();
vm.ItemTreeDataList.Add(new ItemTreeData() { itemId = 1, itemName = "Map", itemIcon = "\xe63c", Children = chi });
vm.ItemTreeDataList.Add(new ItemTreeData() { itemId = 1, itemName = "地图显示", itemIcon = "\xe63c" });
vm.ItemTreeDataList.Add(new ItemTreeData() { itemId = 1, itemName = "Map", itemIcon = "\xe62f" });
vm.ItemTreeDataList.Add(new ItemTreeData() { itemId = 1, itemName = "Map", itemIcon = "\xe643" });
vm.ItemTreeDataList.Add(new ItemTreeData() { itemId = 1, itemName = "Map", itemIcon = "\xe643" });
vm.ItemTreeDataList.Add(new ItemTreeData() { itemId = 1, itemName = "Map", itemIcon = "\xe643" });
vm.ItemTreeDataList.Add(new ItemTreeData() { itemId = 1, itemName = "Map", itemIcon = "\xe643" }); GlobalData.NavModules.Add(new NavModuleInfo() {
region = RegionNames.Main,
module = ModuleNames.Map,
title = ModuleTitle.Map,
icon = "\xe63c",
img = Images.CreateImageSourceFromImage(Properties.Resources.avtar),
menuVm = vm
});
this.moduleTracker.RecordModuleInitialized(ModuleNames.Map);
regionManager.RegisterViewWithRegion(RegionNames.Main, typeof(MapModule_MainView));
}

数据有了,样式有了,下面该关联起来了,其实这步很简单了

在菜单页面订阅一个导航切换的事件,每当模块发生改变时,加载新的模块的菜单数据

这里主要用到Prism的IEventAggregator实现模块之间的通信

 [ImportingConstructor]
public MenuView(IRegionManager regionManager, IEventAggregator eventAggregator, IModuleManager moduleManager)
{
this.eventAggregator = eventAggregator;
//ChangeModuleToMenuEvent cmtmEvent = this.eventAggregator.GetEvent<ChangeModuleToMenuEvent>();
////这里订阅一个改变模块的事件,模块改变时修改menu
//cmtmEvent.Subscribe(OnChangeModuleEvent); NavigateToScreenEvent ntsEvent = GlobalData.EventAggregator.GetEvent<NavigateToScreenEvent>();
ntsEvent.Subscribe(OnLinkageNavigateEvent);
HNavigateToScreenEvent hntsEvent = GlobalData.EventAggregator.GetEvent<HNavigateToScreenEvent>();
hntsEvent.Subscribe(OnLinkageHNavigateEvent);
} public void OnLinkageNavigateEvent(CommandRegionEventArgs e)
{
if (_contentLoaded)
{
LayoutRoot.DataContext = e.menuVm;
}
else {
menuVm = e.menuVm;
}
}

基础的东西都准备好了,现在就算见证奇迹的时刻了,

再加两句代码,在SelectedItemChanged的时候做页面导航

 private void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
ItemTreeData treeData = (ItemTreeData)treeView.SelectedItem;
if (treeData!=null && !string.IsNullOrEmpty(treeData.itemRegion) && !string.IsNullOrEmpty(treeData.itemView))
{
regionManager.RequestNavigate(treeData.itemRegion, treeData.itemView);
}
}

导航这块没遇到啥坑,也就不记录了,

哎,基础差,知识少,理解浅。难得这么顺畅

 

总感觉有些显得小气,分辨率太高 1920*1080?比例分布不均匀?

现在看这大红色儿太刺眼了

到这里框架前台部分基本上已经成型了,后面应该就算调调样式,考虑一下数据怎么取,直接取还是service?还是wcf?

拿什么做服务?现在不都讲究跨平台吗?服务这块最好是拿出来做一个手机或者网页,或者客户端都能用的

 

 

Prism for WPF 搭建一个简单的模块化开发框架(三) 给TreeView加样式做成菜单的更多相关文章

  1. Prism for WPF 搭建一个简单的模块化开发框架 (一个节点)

    原文:Prism for WPF 搭建一个简单的模块化开发框架 (一个节点) 这里我就只贴图不贴代码了,看看这个节点之前的效果 觉得做的好的地方可以范之前的文章看看 有好的建议也可以说说   填充数据 ...

  2. Prism for WPF 搭建一个简单的模块化开发框架(六)隐藏菜单、导航

    原文:Prism for WPF 搭建一个简单的模块化开发框架(六)隐藏菜单.导航 这个实际上是在聊天之前做的,一起写了,也不分先后了 看一下效果图,上面是模块主导航,左侧是模块内菜单,现在加一下隐藏 ...

  3. Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务、WCF消息头添加安全验证Token

    原文:Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务.WCF消息头添加安全验证Token 为什么选择wcf?   因为好像wcf和wpf就是哥俩,,, 为什么选择异步 ...

  4. Prism for WPF 搭建一个简单的模块化开发框架(五)添加聊天、消息模块

    原文:Prism for WPF 搭建一个简单的模块化开发框架(五)添加聊天.消息模块 中秋节假期没事继续搞了搞 做了各聊天的模块,需要继续优化 第一步画页面 页面参考https://github.c ...

  5. Prism for WPF 搭建一个简单的模块化开发框架(二)

    原文:Prism for WPF 搭建一个简单的模块化开发框架(二) 今天又有时间了,再改改,加了一些控件全局的样式 样式代码 <ResourceDictionary xmlns="h ...

  6. Prism for WPF 搭建一个简单的模块化开发框架(一)

    原文:Prism for WPF 搭建一个简单的模块化开发框架(一) 最近闲来无事又想搞搞WPF..... 做个框架吧,可能又是半途而废....总是坚持不下来 不废话了, 先看一下工程结构 布局大概是 ...

  7. 用express搭建一个简单的博客系统

    转自:https://blog.csdn.net/qq_29721837/article/details/62055603 Express 简介 Express 是一个简洁而灵活的 node.js W ...

  8. 从零开始搭建一个简单的基于webpack的vue开发环境

    原文地址:https://segmentfault.com/a/1190000012789253?utm_source=tag-newest 从零开始搭建一个简单的基于webpack的react开发环 ...

  9. 用nodejs搭建一个简单的服务器

    使用nodejs搭建一个简单的服务器 nodejs优点:性能高(读写文件) 数据操作能力强 官网:www.nodejs.org 验证是否安装成功:cmd命令行中输入node -v 如果显示版本号表示安 ...

随机推荐

  1. S/4HANA生产订单的标准状态和透明工厂原型状态的映射

    事务码CO03查看生产订单的状态: 从下面的界面能看出S/4HANA里生产订单在任意时刻可能存在多个状态: 生产订单的ID和状态ID的关系是1:N,维护在数据库表VSAUFK里: 如何把上述SAP系统 ...

  2. 025__name__变量和目录结构规范

    ##__name__变量被其他模块调用的时候就不是main,所以就有这种使用if __name__=='__main__': ##软件目录结构规范为什么要设计好目录结构?"设计项目目录结构& ...

  3. memcached 相关

    今天用了下memcached,把一个日志分析结果的大数组缓存起来,由于实时性跟准确性要求不高,所以缓存一周:因为日志越来越多,不缓存的话每次查看页面会比较慢.(其实可以先离线定期计算好结果存起来).以 ...

  4. Oracle拆分字符串,字符串分割的函数。

    第一种:oracle字符串分割和提取 分割 create or replace function Get_StrArrayLength ( av_str varchar2, --要分割的字符串 av_ ...

  5. slf4j-log4j12-1.5.8.jar有什么用

    slf4j是hibernate的日志接口,通常我们用log4j.jar来实现hibernate的记录日志功能,slf4j-log4j.jar可以看成是用来把slf4j的接口转换成适合log4j的接口的 ...

  6. 汇编试验十五:安装新的int 9中断例程

    安装新的int 9中断例程(按'A'键后显示满屏幕的'A') int 9 是外中断,同样,程序编写还是和其他中断例程类似,安装(复制),调用: 不同点是在于,他要从端口读取数据60h, Source ...

  7. Selenium应用代码(登录)

    这篇可以不看,主要是为了以后的应用代码(传参)做铺垫. import java.awt.Rectangle; import java.awt.image.BufferedImage;import ja ...

  8. springmvc需要掌握的面试知识

     1:讲下Spr ingMvc和Struts1,Struts2的比较的优势 性能上Struts1>SpringMvc>Struts2 开发速度上SpringMvc和Struts2差不多,比 ...

  9. java 编写小工具 尝试 学习(一)

    1.单片机 调试经常 需要  用 串口 工具 发送 一些 特定的  协议或者 命令,每次要 翻译  写成 2进制 很麻烦 ,因此 打算自己用 java 写一个 工具 方便自己  调试,2017年3月2 ...

  10. C# 类中的静态字段始终继承自基类

    我们试想一下现在有一个类Parent,它有一个static的int类型字段number,然后如果类Parent有三个子类Child01.Child02和Child03,那么改变Parent.numbe ...