一、简介

  最近需要开发一个桌面版的工具软件,之前用得更多的是Winform,作为一个全干工程师,我们也要兼顾下WPF,趁此机会再研究下开源控件库。

  MaQaQ:Winform真好用(有个HZHControls控件库,值得一看)。

二、准备工作

  找了下开源控件库,诸如MaterialDesignInXAMLHandyControlAduSkinAdonis-UIPanuon.WPF.UIDMSkin等等,以上这些我们都暂时不看。

  本次选用的控件库是Layui.WPF: GitHub - Layui-WPF-Team/Layui-WPF: 这是一个WPF版的Layui前端UI样式库

  选用的原因是我的渣渣网络在打开其他库的时候都加载很慢,只有它脱颖而出,这就是缘分啊。

  MaQaQ:实际上MaterialDesignInXAML跟HandyControl我之前在别的项目有用过,这两个star数都挺高的,用起来也不错,HandyControl在Gitee上也有库,有兴趣的朋友可以去看看,这次我只是想试试新东西。  

  顺利访问到了GitHub库,我打开了里面的学习文档,他只给了我一个Hello world,真是干!得好。再往下翻,找到了使用说明:

  使用说明很简洁,看起来很轻松就能用上了,但我不信。那我们就去把源码下载下来吧,感恩开发者,他还给了示例(搬砖党狂喜啊)。打开程序源码,根据提示安装了.net5跟.net7后成功加载,找到LayuiApp,这是示例项目:

  运行后界面如下(PS:右上角的公告写得真好,值得一读!!!):

三、开发

  作为一个wpf菜鸡+资深搬砖党,此时不忙搬运,我们先打开LayuiApp的MainWindow.xaml,仔细研究一番:

  可以看到,原项目采用的是prism框架(一个用于构建复杂但组织良好的 WPF 应用程序的框架,实际上我并不认识它,这是通义千问告诉我的),总之,prism:ViewModelLocator.AutoWireViewModel="True"这一句,就是用于自动关联视图与视图模型。

  创建一个新的WPF程序,这里还是用我熟悉的.net6,慎重思考1秒后决定命名为ServerControlSystem,新建的项目里面自带有MainWindow.xaml。

  Nuget上引用LayUI.Wpf和Prism的相关库:

  为了实现prism的自动关联,我们要新建两个文件夹,Views和ViewModels,将MainWindow.xaml移动到Views文件夹下,在ViewModels文件夹中对应新建MainWindowViewModel.cs:

  当然,也可以自定义,这就需要我们自己去修改App.xaml.cs,添加配置:

protected override void ConfigureViewModelLocator()
{
base.ConfigureViewModelLocator();
ViewModelLocationProvider.Register<MainWindow, MainWindowViewModel>();
}

  这里我们还是用的自动关联,因为移动了MainWindow的位置,所以要对应修改下命名空间的路径(不想改你就直接删了重建吧):

  MainWindow.xaml:

<Window x:Class="ServerControlSystem.Views.MainWindow"...>
...
</Window>

  MainWindow.xaml.cs:

public partial class MainWindow : Window

  而在prism框架下,一般要将App的基类改为PrismApplication:

  App.xaml:

<prism:PrismApplication x:Class="ServerControlSystem.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ServerControlSystem"
xmlns:prism="http://prismlibrary.com/">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/LayUI.Wpf;component/Themes/Default.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</prism:PrismApplication>

  App.xaml.cs:

public partial class App : PrismApplication

  同时在prism框架下,一般是通过重写CreateShell方法来指定主窗口,且需要实现继承的RegisterTypes:

public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
DispatcherUnhandledException += App_DispatcherUnhandledException;
}
private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
LayMessage.Error(e.Exception.Message);
//记录日志
e.Handled = true;
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
//注入自定义接口
LayDialog.Register(Container.Resolve<IContainerExtension>());
}
}

  现在,我们可以开始快乐搬运了,先小搬一下MainWindow.xaml,这里我们只是验证控件库的调用,所以就试一下Lay:LayTitleBar:

<Window x:Class="ServerControlSystem.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Lay="clr-namespace:LayUI.Wpf.Controls;assembly=LayUI.Wpf"
xmlns:prism="http://prismlibrary.com/"
Width="1080"
Height="600"
prism:ViewModelLocator.AutoWireViewModel="True"
AllowsTransparency="True"
WindowStartupLocation="CenterScreen"
WindowStyle="None"
Title="MainWindow" >
<Grid>
<Lay:LayTitleBar
Background="{DynamicResource LighCyan}"
CornerRadius="4"
ResizeMode="CanResize"
WindowState="{Binding WindowState, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</Lay:LayTitleBar>
</Grid>
</Window>

  然后再看模型,先实现基类ViewModelBase:

public abstract class ViewModelBase : BindableBase, INavigationAware, IRegionMemberLifetime, IConfirmNavigationRequest
{
/// <summary>
/// 导航器
/// </summary>
public IRegionManager Region;
/// <summary>
/// 弹窗服务
/// </summary>
public IDialogService Dialog;
/// <summary>
/// 事件聚合器
/// </summary>
public IEventAggregator Event;
public ViewModelBase()
{
}
public ViewModelBase(IContainerExtension container)
{
this.Region = container.Resolve<IRegionManager>();
this.Dialog = container.Resolve<IDialogService>();
this.Event = container.Resolve<IEventAggregator>();
}
private DelegateCommand _LoadedCommand;
public DelegateCommand LoadedCommand =>
_LoadedCommand ?? (_LoadedCommand = new DelegateCommand(ExecuteLoadedCommand));
/// <summary>
///初始化界面加载
/// </summary>
public virtual void ExecuteLoadedCommand()
{ }
/// <summary>
/// 控制视图是否被缓存
/// </summary>
public bool KeepAlive => false; public virtual void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
{
continuationCallback(true);
}
/// <summary>
/// 控制实例是否被缓存
/// </summary>
/// <param name="navigationContext"></param>
/// <returns></returns>
public virtual bool IsNavigationTarget(NavigationContext navigationContext)
{
return false;
}
/// <summary>
/// 导航离开当前ViewModel时被调用
/// </summary>
/// <param name="navigationContext"></param>
public virtual void OnNavigatedFrom(NavigationContext navigationContext)
{
}
/// <summary>
/// 导航到当前ViewModel时被调用
/// </summary>
/// <param name="navigationContext"></param>
public virtual void OnNavigatedTo(NavigationContext navigationContext)
{ }
}

  再实现MainWindowViewModel:

public class MainWindowViewModel : ViewModelBase, IWindowAware
{
private WindowState _WindowState;
/// <summary>
/// 窗体状态
/// </summary>
public WindowState WindowState
{
get { return _WindowState; }
set { _WindowState = value; RaisePropertyChanged(); }
}
public MainWindowViewModel(IContainerExtension container) : base(container)
{ }
public override void ExecuteLoadedCommand()
{
base.ExecuteLoadedCommand();
}
public bool CanClosing()
{
var res = MessageBox.Show("确定关闭窗体吗?", "提示", MessageBoxButton.OKCancel);
if (res == MessageBoxResult.OK) return true;
else return false;
}
}

  到这一步基本就完成了,编译生成一下,运行后就能得到一个简陋的空界面:

  之后,就可以根据需要,自己添加控件了。比如,你可以加上,标题栏就会美观一点:

<Lay:LayTitleBar.Header>
<Border Height="40">
</Border>
</Lay:LayTitleBar.Header>

四、总结

  Winform真好写。

C# 从零开始使用Layui.Wpf库开发WPF客户端的更多相关文章

  1. WPF工具开发: 第三库选择

    PropertyGrid Winforms's PropertyGrid 非WPF原生支持, 需要借助WinFormHost 风格不可定制 PropertyInspectorView 算是" ...

  2. MEF 插件式开发 - WPF 初体验

    原文:MEF 插件式开发 - WPF 初体验 目录 MEF 在 WPF 中的简单应用 加载插件 获取元数据 依赖注入 总结 MEF 在 WPF 中的简单应用 MEF 的开发模式主要适用于插件化的业务场 ...

  3. WPF学习开发客户端软件-任务助手(下 2015年2月4日代码更新)

    时光如梭,距离第一次写的 WPF学习开发客户端软件-任务助手(已上传源码)  已有三个多月,期间我断断续续地对该项目做了优化.完善等等工作,现在重新向大家介绍一下,希望各位可以使用,本软件以实用性为主 ...

  4. WPF学习开发客户端软件-任务助手(已上传源码)

    本人纯属WPF新手,布局和WPF的开发水平相当欠缺,从个人来说,还是比较喜欢WPF的,有人说WPF是界面加上WINFORM,我不这样认为,WPF与WINFORM主要的不同在于数据绑定.   这个软件虽 ...

  5. 准备.Net转前端开发-WPF界面框架那些事,值得珍藏的8个问题

    题外话 不出意外,本片内容应该是最后一篇关于.Net技术的博客,做.Net的伙伴们忽喷忽喷..Net挺好的,微软最近在跨平台方面搞的水深火热,更新也比较频繁,而且博客园的很多大牛也写的有跨平台相关技术 ...

  6. WPF Multi-Touch 开发:高效开发模式

    原文 WPF Multi-Touch 开发:高效开发模式 在前几篇文章中已经介绍了触屏操作的多种模式,并对其开发方式也有了进一步了解.细心的朋友应该会发现在上一篇文章中,如果拖动图片过快它会因惯性效果 ...

  7. WPF Multi-Touch 开发:惯性效果(Inertia)

    原文 WPF Multi-Touch 开发:惯性效果(Inertia) 从上一篇实例可以发现在图片移动过程中如果将手指移开屏幕则图片会立刻停止,根据这种情况WPF 提供另外一种惯性效果(Inertia ...

  8. WPF Multi-Touch 开发:高级触屏操作(Manipulation)

    原文 WPF Multi-Touch 开发:高级触屏操作(Manipulation) 在上一篇中我们对基础触控操作有了初步了解,本篇将继续介绍触碰控制的高级操作(Manipulation),在高级操作 ...

  9. WPF Multi-Touch 开发:基础触屏操作(Raw Touch)

    原文 WPF Multi-Touch 开发:基础触屏操作(Raw Touch) 多点触控(Multi-Touch)就是通过与触屏设备的接触达到人与应用程序交互的操作过程.例如,生活中经常使用的触屏手机 ...

  10. WPF 辅助开发工具

    原文:WPF 辅助开发工具 以下介绍的工具均为免费版,有些是源代码开放,希望对大家有用. Kaxaml 轻量级XAML 编辑器,可以同时进行图像和XAML 代码的编辑.最终生成开发人员想要的XAML ...

随机推荐

  1. 整理ML&AI学习路径图

    干货分享: 下面给出一个笔者自己整理的GitHub仓库:https://github.com/isLinXu/awesome-road-map 里面包含了一些可供参考的学习路径和思维导图,并整理微软. ...

  2. 【狂神说Java】Java零基础学习笔记-预科

    [狂神说Java]Java零基础学习笔记-预科 预科01:学习准备:博客 博客,英文名为Blog,它的正式名称为网络日记 为什么要写博客? 需要总结和思考.有时候我们一直在赶路,却忘了放慢脚步 提升文 ...

  3. flutter 的一些概念三

    本文同步发布于公众号:stringwu的互联网杂谈:flutter 的一些概念三 1 Stream 与 Future的关系 Stream 和 Future 都是 Flutter 中常用的异步编程模型, ...

  4. Docker实践:Centos下安装Docker并简单的使用

    1 环境介绍 版本信息: [root@localhost]#  cat /proc/version Linux version 3.10.0-514.el7.x86_64 (builder@kbuil ...

  5. CCS(TI IDE)中英文切换

    介绍 使用CSS时会遇到中英文切换的问题,使用中文可以方便我们更好的开发,但是由于一些专业名词的原因我们有时候又需要英文环境,所以中英文切换就显得十分重要. 由于CCS基于eclipse开发,所以CC ...

  6. Cockpit pg walkthrough Intermediate

    nmap 发现两个 web站 80 和 9090 还有 22端口 dirsearch 发现80端口有login.php 登录界面 发现没有弱口令 测试sql注入 测试了一会发现密码 password= ...

  7. ctfshow--web1

    第一题很简单 就是一个base64编码 我们打开开发者模式看源代码 Y3Rmc2hvd3s1MGMyZDdkYS1lOWZjLTQ5YzItYTRjZC1iZmJmZjIyYmI4NWV9将这段话ba ...

  8. RocketMQ实战—4.消息零丢失的方案

    大纲 1.全链路分析为什么用户支付完成后却没有收到红包 2.RocketMQ的事务消息机制实现发送消息零丢失 3.RocketMQ事务消息机制的底层实现原理 4.是否可以通过同步重试方案来代替事务消息 ...

  9. VXLAN 网络中报文转发过程

    本文分享自天翼云开发者社区<VXLAN 网络中报文转发过程>,作者:刘****林 以同网段的 VM 间互通简单介绍 VXLAN 网络中的报文转发过程. 1.VM1 发送目的地址为 VM2 ...

  10. 魔乐社区体验:探索Llama 3.1模型微调之旅

    在2024年的AI领域,Meta发布的Llama 3.1模型无疑成为了研究者和开发者的新宠.我有幸通过魔乐社区提供的资源,对这一模型进行了深入的学习和实践.在这个过程中,魔乐社区的资源和支持给我留下了 ...