十年河东,十年河西,莫欺少年穷
学无止境,精益求精
实现的效果:
1、初始化Prism
1.1、项目引入如下包
1.2、按照Prism规则,项目中创建如下文件夹
Prism 规则:必须将窗体放入 Views文件夹中,窗体名称必须以View结尾,必须将数据上下文放入ViewModels文件夹中,上下文类必须以Model结尾
另外两个文件夹分为存放用户控件 及 用户控件使用的数据类
新建窗体MainView 和 MainViewModel、新建用户控件IndexView 和 IndexViewModel、新建用户控件UserView 和 UserViewModel (其实用户控件及上下文类无需遵守Prism规则)
1.3、初始化App.xaml 及 App.cs
App.cs
using Prism.DryIoc;
using Prism.Ioc;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using WpfApp.UserControls;
using WpfApp.ViewModels;
using WpfApp.Views;
namespace WpfApp
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve<MainView>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<IndexView, IndexViewModel>();
containerRegistry.RegisterForNavigation<UserView, UserViewModel>();
}
}
}
View Code
App.Xaml
<Prism:PrismApplication x:Class="WpfApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:WpfApp" >
<Application.Resources>
</Application.Resources>
</Prism:PrismApplication>
View Code
App.cs 中重新了二个方法,第一个方法为设定启动窗口,第二个方法为注册导航(两个用户控件为填充内容)
App.xaml 中引入 Prism 命名空间,及改造根节点
2、App.xaml 引入MaterialDesign
MaterialDesign 的GitHub地址为: https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit
按照文档引入MaterialDesign,App.xaml 变更为:
<Prism:PrismApplication x:Class="WpfApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:WpfApp" >
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="DeepPurple" SecondaryColor="Lime" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
</ResourceDictionary.MergedDictionaries>
<!--自定义样式 样式名:MyListBoxItemStyle,样式挂载:ListBoxItem-->
<Style x:Key="MyListBoxItemStyle" TargetType="ListBoxItem">
<!--自定义高度-->
<Setter Property="MinHeight"
Value="48" />
<Setter Property="Template">
<Setter.Value>
<!--影响属性 ListBoxItem-->
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<Border x:Name="borderHeader" />
<Border x:Name="border" />
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
</Grid>
<!--触发器-->
<ControlTemplate.Triggers>
<!--ListBoxItem点击时触发-->
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderThickness"
TargetName="borderHeader" Value="4,0,0,0"/>
<Setter Property="BorderBrush"
TargetName="borderHeader"
Value="{DynamicResource PrimaryHueLightBrush}" />
<Setter TargetName="border"
Property="Background"
Value="{DynamicResource PrimaryHueLightBrush}" />
<Setter TargetName="border"
Property="Opacity"
Value="0.4" />
</Trigger>
<!--鼠标悬停触发器触发器-->
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border"
Property="Background"
Value="{DynamicResource PrimaryHueLightBrush}" />
<Setter TargetName="border"
Property="Opacity"
Value="0.1" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Application.Resources>
</Prism:PrismApplication>
View Code
2.1、检测是否成功引入 MaterialDesign
在 MainView 中添加一个按钮
<Grid>
<Button Content="检测是否成功引入" FontSize="30" Height="80" Width="280"/>
</Grid>
出现如下样式,则证明引入成功
3、改造MainView
先贴出MainView.xaml 代码如下:
<Window x:Class="WpfApp.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp.Views"
mc:Ignorable="d"
xmlns:Prism="http://prismlibrary.com/"
Prism:ViewModelLocator.AutoWireViewModel="True"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
Background="{DynamicResource MaterialDesignPaper}"
TextElement.FontWeight="Medium"
FontFamily="{materialDesign:MaterialDesignFont}"
TextElement.FontSize="14"
WindowStyle="None"
WindowStartupLocation="CenterScreen"
Title="MainView" Height="768" Width="1280">
<Window.Resources>
<ResourceDictionary>
<!--<Style TargetType="ListBoxItem" x:Key="Ls">
<Setter Property="MinHeight" Value="40"/>
<Setter Property="BorderThickness" Value="4,0,4,0"/>
</Style>-->
</ResourceDictionary>
</Window.Resources>
<materialDesign:DialogHost DialogTheme="Inherit"
Identifier="RootDialog"
SnackbarMessageQueue="{Binding ElementName=MainSnackbar, Path=MessageQueue}">
<materialDesign:DrawerHost x:Name="drawerHost" IsLeftDrawerOpen="{Binding ElementName=MenuToggleButton, Path=IsChecked}" Background="Transparent">
<materialDesign:DrawerHost.LeftDrawerContent>
<DockPanel MinWidth="220" Background="Transparent">
<ToggleButton Margin="16"
HorizontalAlignment="Right"
DockPanel.Dock="Top"
IsChecked="{Binding ElementName=MenuToggleButton, Path=IsChecked, Mode=TwoWay}"
Style="{StaticResource MaterialDesignHamburgerToggleButton}" />
<ListBox ItemsSource="{Binding menuBars}" ItemContainerStyle="{StaticResource MyListBoxItemStyle}" x:Name="menubar">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding ListBoxItemChangedCommand}" CommandParameter="{Binding ElementName=menubar,Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Background="Transparent" VerticalAlignment="Center">
<materialDesign:PackIcon Kind="{Binding MenuIcon}" Margin="15,0"/>
<TextBlock Text="{Binding MenuName}" Margin="10,0" FontSize="16"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</materialDesign:DrawerHost.LeftDrawerContent>
<DockPanel>
<materialDesign:ColorZone Padding="16" x:Name="ColorZone"
materialDesign:ElevationAssist.Elevation="Dp4"
DockPanel.Dock="Top"
Mode="PrimaryMid">
<DockPanel LastChildFill="False">
<StackPanel Orientation="Horizontal">
<ToggleButton x:Name="MenuToggleButton"
AutomationProperties.Name="HamburgerToggleButton"
IsChecked="False"
Style="{StaticResource MaterialDesignHamburgerToggleButton}" />
<Button Margin="24,0,0,0"
materialDesign:RippleAssist.Feedback="{Binding RelativeSource={RelativeSource Self}, Path=Foreground, Converter={StaticResource BrushRoundConverter}}"
Command="{Binding BtnBack}"
Content="{materialDesign:PackIcon Kind=ArrowLeft,
Size=24}"
Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}"
Style="{StaticResource MaterialDesignToolButton}"
ToolTip="Previous Item" Cursor="Hand" />
<Button Margin="16,0,0,0"
materialDesign:RippleAssist.Feedback="{Binding RelativeSource={RelativeSource Self}, Path=Foreground, Converter={StaticResource BrushRoundConverter}}"
Command="{Binding BtnForward}"
Content="{materialDesign:PackIcon Kind=ArrowRight,
Size=24}"
Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}"
Style="{StaticResource MaterialDesignToolButton}"
ToolTip="Next Item" Cursor="Hand" />
<Button Margin="16,0,0,0"
materialDesign:RippleAssist.Feedback="{Binding RelativeSource={RelativeSource Self}, Path=Foreground, Converter={StaticResource BrushRoundConverter}}"
Command="{Binding HomeCommand}"
Content="{materialDesign:PackIcon Kind=Home,
Size=24}"
Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}"
Style="{StaticResource MaterialDesignToolButton}"
ToolTip="Home" />
</StackPanel>
<TextBlock Margin="20,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
AutomationProperties.Name="Material Design In XAML Toolkit"
FontSize="22"
Text="Material Design In XAML Toolkit" />
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal">
<TextBlock Text="hi,wpf" Margin="0 ,8,10,0" FontSize="18" Foreground="#ffc"/>
<Image Source="/images/tx.jpg" Width="25" Height="25" Margin="10 0">
<Image.Clip>
<EllipseGeometry RadiusX="12.5" RadiusY="12.5" Center="12.5,12.5"/>
</Image.Clip>
</Image>
<Button x:Name="btnMin" Content="―" Margin="5 0"/>
<Button x:Name="btnMax" Content="☐" Margin="5 0"/>
<Button x:Name="btnClose" Content="✕" Margin="5 0"/>
</StackPanel>
</DockPanel>
</materialDesign:ColorZone>
<ContentControl Prism:RegionManager.RegionName="MainViewRegionName" />
</DockPanel>
</materialDesign:DrawerHost>
</materialDesign:DialogHost>
</Window>
View Code
3.1、针对xaml说明如下:
<Window x:Class="WpfApp.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp.Views"
mc:Ignorable="d"
xmlns:Prism="http://prismlibrary.com/" --引入Prism命名空间
Prism:ViewModelLocator.AutoWireViewModel="True" --根据Prism规则,自动匹配数据上下文DataContext
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" --引入MaterialDesgin 样式库
xmlns:i="http://schemas.microsoft.com/xaml/behaviors" --引入行为,用于处理ListBoxItem点击事件
TextElement.Foreground="{DynamicResource MaterialDesignBody}" --引入 MaterialDesign 颜色
Background="{DynamicResource MaterialDesignPaper}" --引入动态资源
TextElement.FontWeight="Medium" --引入MaterialDesign 字体
FontFamily="{materialDesign:MaterialDesignFont}" --引入 materialDesign 字体
TextElement.FontSize="14" --设置字号
WindowStyle="None" --去掉窗体边框
WindowStartupLocation="CenterScreen" --启动后,默认居中
Title="MainView" Height="768" Width="1280">
3.2、双击事件、最大、最小按钮事件、拖拽事件
/// <summary>
/// MainView.xaml 的交互逻辑
/// </summary>
public partial class MainView : Window
{
public MainView()
{
InitializeComponent();
//最小化
btnMin.Click += (s, e) => { this.WindowState = WindowState.Minimized; };
//最大化
btnMax.Click += (s, e) =>
{
if (this.WindowState == WindowState.Normal)
{
this.WindowState = WindowState.Maximized;
}
else
{
this.WindowState = WindowState.Normal;
}
};
//关闭事件
btnClose.Click += (s, e) => { this.Close(); };
//鼠标拖拽事件
ColorZone.MouseMove += (s, e) =>
{
if (e.LeftButton == MouseButtonState.Pressed)
{
this.DragMove();
}
};
//鼠标双击导航栏事件
ColorZone.MouseDoubleClick += (s, e) =>
{
if (this.WindowState == WindowState.Normal)
{
this.WindowState = WindowState.Maximized;
}
else
{
this.WindowState = WindowState.Normal;
}
};
menubar.SelectionChanged += (s, e) =>
{
drawerHost.IsLeftDrawerOpen = false;
};
}
}
View Code
3.3、MainViewModel如下:
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
namespace WpfApp.ViewModels
{
public class MainViewModel : BindableBase
{
public ObservableCollection<MenuBarDto> menuBars { get; set; }
public DelegateCommand<MenuBarDto> ListBoxItemChangedCommand { get; private set; }
public DelegateCommand BtnBack { get; private set; }
public DelegateCommand BtnForward { get; private set; }
/// <summary>
/// 区域管理器-跳转相关
/// </summary>
private readonly IRegionManager regionManager;
/// <summary>
/// 用于保存路由跳转记录
/// </summary>
private IRegionNavigationJournal journal;
public MainViewModel(IRegionManager regionManager)
{
CreateMenus();
this.regionManager = regionManager;
ListBoxItemChangedCommand = new DelegateCommand<MenuBarDto>(GoMenuBar);
BtnBack = new DelegateCommand(Back);
BtnForward = new DelegateCommand(Forward);
}
private void GoMenuBar(MenuBarDto obj)
{
//参考:MainView.Xaml 中的 <ContentControl Prism:RegionManager.RegionName="MainViewRegionName" />
regionManager.Regions["MainViewRegionName"].RequestNavigate(obj.MenuPath, navigationCallback);
}
private void navigationCallback(NavigationResult obj)
{
if (obj.Result.Value)
{
//如果跳转成功,则存储跳转记录
journal = obj.Context.NavigationService.Journal;
}
}
/// <summary>
/// 返回上一页
/// </summary>
private void Back()
{
if (journal != null && journal.CanGoBack)
{
journal.GoBack();
}
}
/// <summary>
/// 返回下一页
/// </summary>
private void Forward()
{
if (journal != null && journal.CanGoForward)
{
journal.GoForward();
}
}
private void CreateMenus()
{
menuBars = new ObservableCollection<MenuBarDto>();
menuBars.Add(new MenuBarDto() { MenuIcon = "Home", MenuName = "首页", MenuPath = "IndexView" });
menuBars.Add(new MenuBarDto() { MenuIcon = "User", MenuName = "用户管理", MenuPath = "UserView" });
menuBars.Add(new MenuBarDto() { MenuIcon = "NotebookOutline", MenuName = "备忘录", MenuPath = "MemoView" });
menuBars.Add(new MenuBarDto() { MenuIcon = "Cog", MenuName = "设置", MenuPath = "SetingView" });
}
}
public class MenuBarDto
{
public string MenuName { get; set; }
public string MenuIcon { get; set; }
public string MenuPath { get; set; }
}
}
View Code
说明如下:
上述代码设计 导航跳转,导航记录,上一页,下一页等功能,不懂的小伙伴这里就不解释了。
最终效果图: