下面我们将讲解在WPF中使用Blazor,并且使用Blazor做一些文件编辑操作,下面是需要用到的东西

  • WPF
  • Blazor
  • Masa Blazor
  • Monaco

安装Masa Blazor模板

使用CMD指令安装模板

dotnet new install MASA.Template

新建Masa Blazor WPF App

  1. 找到如图的模板,然后点击下一步

  2. 下一步,新建项目名称FileEditor

添加Monaco

  1. 打开wwwroot/index.html,并且引用Monaco的依赖,将一下依赖添加到body里面的最尾部。
<script>
var require = { paths: { 'vs': 'https://cdn.masastack.com/npm/monaco-editor/0.34.1/min/vs' } };
</script>
<script src="https://cdn.masastack.com/npm/monaco-editor/0.34.1/min/vs/loader.js"></script>
<script src="https://cdn.masastack.com/npm/monaco-editor/0.34.1/min/vs/editor/editor.main.nls.js"></script>
<script src="https://cdn.masastack.com/npm/monaco-editor/0.34.1/min/vs/editor/editor.main.js"></script>
  1. 新建Pages/Index.razor.cs文件
using System.IO;
using System.Text;
using Masa.Blazor;
using Masa.Blazor.Presets;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop; namespace FileEditor.Pages; public partial class Index : IDisposable
{
/// <summary>
/// 文本内容
/// </summary>
private string value; private MMonacoEditor _editor; private DotNetObjectReference<Index>? _objRef; /// <summary>
/// 定义Monaco的初始配置
/// </summary>
private object options = new
{
language = "md", // 设置语法
automaticLayout = true, // 高度自适应
theme = "vs-dark", // 主题
}; private string fullName; protected override void OnInitialized()
{
_objRef = DotNetObjectReference.Create(this);
} /// <summary>
/// 具体文件路径
/// </summary>
[Parameter]
[CascadingParameter(Name = nameof(FullName))]
public string FullName
{
get => fullName;
set
{
fullName = value;
UpdateValue();
}
} /// <summary>
/// Monaco初始化事件
/// </summary>
private async Task InitMonaco()
{
// 监听CTRL+S 2097 = CTRL+S 快捷键
// 调用Monaco的Command,传递当前对象,并且指定当触发快捷键的时候调用当签对象的指定方法。
await _editor.AddCommandAsync(2097, _objRef, nameof(SaveValue));
} /// <summary>
/// 更新value
/// </summary>
private void UpdateValue()
{
if (string.IsNullOrEmpty(fullName))
{
return;
} var info = new FileInfo(fullName);
if (!info.Exists) return;
using var fileStream = info.OpenText();
value = fileStream.ReadToEnd();
} /// <summary>
/// 更新文件内容
/// </summary>
[JSInvokable]
public async Task SaveValue()
{
try
{
await using var fileStream = File.OpenWrite(fullName);
fileStream.Position = 0;
await fileStream.WriteAsync(Encoding.UTF8.GetBytes(value));
fileStream.Close();
}
catch (Exception e)
{
await PopupService.EnqueueSnackbarAsync(new SnackbarOptions()
{
Title = "保存文件错误",
Content = e.Message
});
}
} public void Dispose()
{
_editor.Dispose();
_objRef?.Dispose();
}
}

Index.razor.cs文件中我们实现了拦截FullName的set,当被set的时候说明上级组件选择了文件并且通过CascadingParameter传递了参数到当前组件。

并且对于当前的Value进行更新,

打开Index.razor

@page "/"
@inject IPopupService PopupService <MMonacoEditor InitCompleteHandle="async () => await InitMonaco()"
@bind-Value="value"
Height="@("100%")"
EditorOptions="options" @ref="_editor">
</MMonacoEditor>

我们对于cs的一些方法和参数进行了绑定,并且bind-value了value的值,我们在cs文件中更新了value就自动更新了UI的显示的值。

然后我们打开Shared/MainLayout.razor文件添加打开文件选择器,从而选择文件。

@using Microsoft.Win32
@inherits LayoutComponentBase <MApp>
<MAppBar App>
<MAppBarNavIcon @onclick="() => _drawer = !_drawer"></MAppBarNavIcon>
<MToolbarTitle>FileEditor</MToolbarTitle>
<MButton OnClick="OpenFile">打开文件</MButton>
<MSpacer></MSpacer>
<MButton Text Color="primary" Target="_blank" Href="https://docs.masastack.com/blazor/introduction/why-masa-blazor">About</MButton>
</MAppBar> <MNavigationDrawer App @bind-Value="_drawer">
<MList Nav Routable>
<MListItem Href="/" ActiveClass="primary--text">
<MListItemIcon>
<MIcon>mdi-home</MIcon>
</MListItemIcon>
<MListItemContent>
<MListItemTitle>Home</MListItemTitle>
</MListItemContent>
</MListItem>
<MListItem Href="/counter" ActiveClass="primary--text">
<MListItemIcon>
<MIcon>mdi-plus</MIcon>
</MListItemIcon>
<MListItemContent>
<MListItemTitle>Counter</MListItemTitle>
</MListItemContent>
</MListItem>
<MListItem Href="/fetchdata" ActiveClass="primary--text">
<MListItemIcon>
<MIcon>mdi-list-box</MIcon>
</MListItemIcon>
<MListItemContent>
<MListItemTitle>Fetch data</MListItemTitle>
</MListItemContent>
</MListItem>
</MList>
</MNavigationDrawer> <MMain>
<MContainer Fluid Style="height: 100%">
<CascadingValue Value="fullName" Name="FullName">
<MErrorHandler>
@Body
</MErrorHandler>
</CascadingValue>
</MContainer>
</MMain>
</MApp> @code { private bool? _drawer; private string fullName; private void OpenFile()
{
var openFileDialog = new OpenFileDialog();
openFileDialog.Title = "请选择您的文件";
openFileDialog.Filter = "文本文件 (*.txt, *.md)|*.txt;*.md";
bool? result = openFileDialog.ShowDialog();
if (result == true)
{
fullName = openFileDialog.FileName;
}
}
}

在这里我们将使用Microsoft.Win32.OpenFileDialog打开文件选择器,并且指定选择文件的类型,

当前文件选择器返回true,则fullName的值,fullName则会通过CascadingValue组件的绑定传递到<CascadingValue></CascadingValue>内的所有子组件。

下面我们看看实际使用效果。

技术交流

qq群:452761192

wx:wk28u9123456789(请备注技术交流)

源码下载地址:https://code-token.oss-cn-beijing.aliyuncs.com/FileEditor.zip

WPF使用Blazor的快速案例的更多相关文章

  1. angularjs 2.0 快速案例(1)

    前言 上一节我们已经把环境给搭建起来了,现在我们通过一个快速案例把angular 2.0 初步了解一下,后续我们会深入每一个细节,这个案例主要是一个[英雄(Hero)]列表的展示,创建,编辑.这个案例 ...

  2. 在WPF的DATAGRID中快速点击出现在ADDNEW或EDITITEM事务过程不允许DEFERREFRESH

    原文 在WPF的DATAGRID中快速点击出现在ADDNEW或EDITITEM事务过程不允许DEFERREFRESH 在项目中关于DataGrid的遇到过一些问题,其中是关于迁入CheckBox的双向 ...

  3. 浅析MyBatis(一):由一个快速案例剖析MyBatis的整体架构与运行流程

    MyBatis 是轻量级的 Java 持久层中间件,完全基于 JDBC 实现持久化的数据访问,支持以 xml 和注解的形式进行配置,能灵活.简单地进行 SQL 映射,也提供了比 JDBC 更丰富的结果 ...

  4. WPF 4.0 DatePicker 快速录入

    WPF 4.0的DatePicker在通过键盘录入日期的时候是非常让人郁闷的.必须按照日期的格式来完整输入例如,比如输入“2010/10/10”才能识别.而实际上在一些要求快速录入的场合,用户更希望直 ...

  5. WPF简单的口算案例

    前几天在博客园,看到有博友利用Winform做了一个口算案例,于是我想把它移植在WPF程序中.Winform程序:http://www.cnblogs.com/ImYZF/p/3345452.html ...

  6. WPF中利用DynamicDataDisplay快速实现示波器功能

    DynamicDataDisplay控件是一个功能很强的绘图工具,除了能生成曲线外,还有很多其他功能,具体见http://dynamicdatadisplay.codeplex.com/.这里你也能下 ...

  7. 【炫丽】从0开始做一个WPF+Blazor对话小程序

    大家好,我是沙漠尽头的狼. .NET是免费,跨平台,开源,用于构建所有应用的开发人员平台. 本文演示如何在WPF中使用Blazor开发漂亮的UI,为客户端开发注入新活力. 注 要使WPF支持Blazo ...

  8. Smart Tag——DevExpress WPF初探

    Smart Tag是一个设计时扩展,所有标准控件均自带这个功能,当然也包括 DevExpress WPF Controls .可以快速设置控件的值或者绑定最重要的属性.它还可以帮助你完成一些重复的工作 ...

  9. ASP.NET Core Blazor Webassembly 之 渐进式应用(PWA)

    Blazor支持渐进式应用开发也就是PWA.使用PWA模式可以使得web应用有原生应用般的体验. 什么是PWA PWA应用是指那些使用指定技术和标准模式来开发的web应用,这将同时赋予它们web应用和 ...

  10. 如何使用MASA.Blazor

    MASA.Blazor 是什么? 基于Material Design设计和BlazorComponent的交互能力提供标准的基础组件库.提供如布局.弹框标准.Loading.全局异常处理等标准场景的预 ...

随机推荐

  1. lec-1-Deep Reinforcement Learning, Decision Making, and Control

    What is RL 基于学习的决策的数学形式 从经验中学习决策和控制的方法 Why should we study this now 深度神经网络特征方法 强化学习的提升 计算能力的提升 我们还需要 ...

  2. [安全开发] SQL注入扫描(一股子GPT味~)

    实际上大部分都是它写的,它真我哭 SQL注入扫描就是一种用于检测和预防SQL注入攻击的工具.它通过模拟SQL注入攻击的方式,向目标网站发送特定的SQL查询语句,以验证目标网站是否存在SQL注入漏洞.S ...

  3. 【模型部署 01】C++实现分类模型(以GoogLeNet为例)在OpenCV DNN、ONNXRuntime、TensorRT、OpenVINO上的推理部署

    深度学习领域常用的基于CPU/GPU的推理方式有OpenCV DNN.ONNXRuntime.TensorRT以及OpenVINO.这几种方式的推理过程可以统一用下图来概述.整体可分为模型初始化部分和 ...

  4. 【lwip】15-NETCONN接口

    前言 终于到接口层了. 原文:李柱明博客:https://www.cnblogs.com/lizhuming/p/17442931.html ‍ 框架描述 前面我们已经学完了,都知道raw接口了,其实 ...

  5. Rust中的变量的声明和定义

    变量的声明和定义 Rust中合法的标识符(包括变量名.函数名.triat名等)必须由数字.字母.下划线组成,而且不能以数字开头.这个和很多语言都是一样的.Rust将来也会允许其他Unicode字符作为 ...

  6. Cronjob 定时任务

    Job: 负责处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个Pod成功结束. CronJob: 则就是在Job上加上了时间调度. 我们用Job这个资源对象来创建一个任务,我们定一个Job来 ...

  7. rabbitmq安装部署和常用命令

    python操作rabbitmq rabbitmq实现可以使用java或者springboot的封装方法,自己创建实现,也可以使用中间件实现,相对于自建,使用rabbitmq应用场景及使用更系统安全. ...

  8. 自然语言处理 Paddle NLP - 开放域对话系统-理论

    常见的对话系统 个人助手 •Apple Siri, Amazon Alexa, Baidu Xiaodu 客户服务•餐厅预定.商品咨询.债务催收 休闲娱乐 •Microsoft XiaoIce,Rep ...

  9. 聊天室(二)__ unipush 推送实现详细教程

    一.推送作用 推送作用我就不废话了,能做推送的都知道作用,直接上干货. 二.unipush 快速开通   Dcloud 开发者实名认证注册账号,绑定对应的 app 信息. uni-push产品有2个入 ...

  10. iphone拍照的历史顽固问题-鬼影

    iphone11 系列的鬼影问题 近期苹果 iPhone 11 系列的手机又出现了新问题,其中有不少网友表示,自己在用手机拍照后,图片中莫名出现了"鬼影"的现象,这次的" ...