先看一下效果吧: 我們直接通過改造一下原版的TreeView來實現上面這個效果 我們先創建一個普通的TreeView 代碼很簡單: <TreeView> <TreeViewItem Header="人事部"/> <TreeViewItem Header="技術部"> <TreeViewItem He ...
先看一下效果吧:
我們直接通過改造一下原版的TreeView來實現上面這個效果
我們先創建一個普通的TreeView
代碼很簡單:
<TreeView> <TreeViewItem Header="人事部"/> <TreeViewItem Header="技術部"> <TreeViewItem Header="技術部-1"/> <TreeViewItem Header="技術部-1"/> </TreeViewItem> <TreeViewItem Header="財務部"/> </TreeView>
實現的效果如下:
如果把這個當成是項目的菜單欄,應該會被領導罵死,一個是不夠靈活,數據是寫死的;二是樣式不好看,只有點文字部分才會展開。
創建一下模板
直接在設計器中右鍵我們的item,編輯副本,點擊確定,我們會得到下麵一段代碼
裡面有一個叫Bd的border,我們把這個border的背景色去掉,然後我們自己去創建兩個新的border
<Border Background="Transparent" Margin="-200,0,-200,0" Grid.ColumnSpan="4"/> <Border x:Name="bd1" Background="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" Margin="-200,0,-200,0" Visibility="Hidden" Grid.ColumnSpan="4"> <Border.Effect> <DropShadowEffect BlurRadius="5" ShadowDepth="2"/> </Border.Effect> </Border> <ToggleButton x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource Mode=TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}"/> <Border x:Name="Bd" Grid.Column="1" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"> <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </Border>
上面紅色部分是我們新增的兩個border,原本的叫Bd的border,我們只保留紫色部分的屬性.
原本的代碼裡面有兩個關於Bd的trigger
我們取名為bd1的border,最開始的Visibility設置的是Hidden,我們替換一下關於Bd的trigger,讓它變成當IsSelected是true的情況下,讓bd1的Visibility變成Visible.
<Trigger Property="IsSelected" Value="true"> <Setter Property="Visibility" TargetName="bd1" Value="Visible"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsSelected" Value="true"/> <Condition Property="IsSelectionActive" Value="false"/> </MultiTrigger.Conditions> <Setter Property="Visibility" TargetName="bd1" Value="Visible"/> <Setter Property="Background" TargetName="bd1" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
再運行一下,看一下效果
基本上已經算是成功一半了,但是這個時候,我們的菜單隻有一個有效果,其他的還是原來的樣式,那是因為我們只有一個TreeViewItem使用了我們寫的效果
如果我們每一個TreeViewItem都複製一下這句Style="{DynamicResource TreeViewItemStyle1}" ,是不是顯得很呆,而且這隻是在我們的菜單很少的情況下,如果菜單很多,這個方法就不可行。
所以這裡我們用一個TreeView的ItemContainerStyle來操作一下
<Style x:Key="treeViewStyle1" TargetType="{x:Type TreeView}" BasedOn="{StaticResource {x:Type TreeView}}"> <Setter Property="ItemContainerStyle" Value="{StaticResource TreeViewItemStyle1}"/> </Style>
我們創建一個類型是TreeView的style,把它的ItemContainerStyle設置成我們之前添加的那個style,然後我們把這個style放到我們的TreeView上
這個時候我們再運行就會發現首級菜單的樣式都實現我們想要的效果了,但是子集菜單還是原來的樣式
我們在代碼裡面添加下麵一個方法
private void ApplyItemContainerStyle(ItemsControl itemsControl) { foreach (var item in itemsControl.Items) { var treeViewItem = item as TreeViewItem; if (treeViewItem != null) { treeViewItem.Style = treeview1.ItemContainerStyle; ApplyItemContainerStyle(treeViewItem); } } }
然後我們在構造函數裡面把我們的TreeView當做是參數傳進去
這個方法就是把所有的item和item的子項都設置成treeview的ItemContainerStyle;
我們再啟動一下項目,就會發現效果是我們想要的效果了
到這裡其實大部分效果都實現了,基本上也可以向領導交差了;
但是還缺少一個數據可拓展性和一個圖標的功能,我們先看一下數據可拓展性
在平時的項目裡面,一般都會有很多個不同的項目,每個項目可能都有好多個菜單,有的項目還想隱藏某一些菜單,我們總不能所有項目都通過visible屬性來設置吧
特別是報表功能可能會有幾十個,所以我們需要用到一個東西叫數據模板:HierarchicalDataTemplate;
我們先創建一個類
public class TreeViewModel { public string Header { get; set; } public ObservableCollection<TreeViewModel> Children { get; set; } }
然後回到設計器裡面,把我們的代碼改成下麵的代碼
<TreeView Style="{DynamicResource treeViewStyle1}" x:Name="treeview1"> <TreeView.ItemTemplate> <HierarchicalDataTemplate DataType="{x:Type local:TreeViewModel}" ItemsSource="{Binding Children}"> <StackPanel Height="40" Orientation="Horizontal"> <TextBlock Text="{Binding Header}" VerticalAlignment="Center"/> </StackPanel> </HierarchicalDataTemplate> </TreeView.ItemTemplate> </TreeView>
對比一下紅色部分的綁定,和類的屬性,就能知道這個數據模板怎麼用了.
再到構造函數裡面去添加數據
public ObservableCollection<TreeViewModel> MenuCollection { get; set; } public MainWindow() { InitializeComponent(); MenuCollection = new ObservableCollection<TreeViewModel>() { new TreeViewModel { Header = "人事部" }, new TreeViewModel { Header = "技術部", Children = new ObservableCollection<TreeViewModel> { new TreeViewModel { Header = "技術部-1"}, new TreeViewModel { Header = "技術部-2"}, } }, new TreeViewModel { Header = "財務部", }, }; treeview1.ItemsSource = MenuCollection; }
註意這兩段標紅的代碼,我們用一個集合MenuCollection模擬一下我們從資料庫或者其他地方查詢出來的菜單集合,然後把它做為數據源給treeview就可以了
再運行一下項目,它就差不多實現我們想要的效果了,現在再去找領導交差,領導還會誇你做的不錯,只是還差一個圖標了,這個就是錦上添花的東西了.
我們百度搜索一下 阿裡ICON,去到官網裡面,創建一個自己的賬號,然後搜索一些自己喜歡的圖標
把自己喜歡的圖標添加到自己的項目中去,這裡的項目名很重要,我取的是 FatSheep
在到我的項目裡面去把這個資源文件下載到自己的項目中
下載下來的文件,我們把ttf尾碼的文件添加到我們的項目裡面去
把它作為資源引入到代碼裡面
<FontFamily x:Key="FatSheep">pack:application:,,,/自己項目的名字;component/Resources/iconfont.ttf#FatSheep</FontFamily>
記得修改一下自己的項目名字,我取的是TreeViewDemo,改成自己的項目名就好了,最後的結尾,是FatSheep,記得改成自己的ICON項目名稱
接著我們在TreeViewModel裡面添加一個Icon屬性
public class TreeViewModel { public string Header { get; set; } public string Icon { get; set; } public ObservableCollection<TreeViewModel> Children { get; set; } }
然後我們在數據源裡面添加一下數據
MenuCollection = new ObservableCollection<TreeViewModel>() { new TreeViewModel { Header = "人事部", Icon = "\ue71c" }, new TreeViewModel { Header = "技術部", Icon = "\ue71c", Children = new ObservableCollection<TreeViewModel> { new TreeViewModel { Header = "技術部-1", Icon="\ue71c"}, new TreeViewModel { Header = "技術部-2" , Icon="\ue71c"}, } }, new TreeViewModel { Header = "財務部", Icon = "\ue71c" }, };
設計器裡面添加一下顯示部分的代碼
<TreeView Style="{StaticResource treeViewStyle1}" x:Name="treeView1" BorderThickness="0,0,1,0" Grid.Column="1"> <TreeView.ItemTemplate> <HierarchicalDataTemplate DataType="{x:Type local:TreeViewModel}" ItemsSource="{Binding Children}"> <StackPanel Height="40" Orientation="Horizontal"> <TextBlock Text="{Binding Icon}" VerticalAlignment="Center" FontFamily="{StaticResource FatSheep}" Margin="0,0,5,0"/> <TextBlock Text="{Binding Header}" VerticalAlignment="Center"/> </StackPanel> </HierarchicalDataTemplate> </TreeView.ItemTemplate> </TreeView>
再啟動項目,功能就完成了
這個笑臉是怎麼來的了
那是因為我自己的項目裡面添加了一個笑臉
我們複製一下這個代碼,  我們把它改成 \ue71c,這是一個轉義字元,就這樣我們就能添加如何自己喜歡的圖標了。
項目github地址:bearhanQ/WPFFramework: Share some experience (github.com)
QQ技術交流群:332035933;
歡迎進群討論問題,不論是winform,還是wpf,還是.net core的,還有很多萌妹.