• WPF使用Blazor的快速案例


    下面我们将讲解在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
    {
        /// 
        /// 文本内容
        /// 
        private string value;
    
        private MMonacoEditor _editor;
    
        private DotNetObjectReference? _objRef;
    
        /// 
        /// 定义Monaco的初始配置
        /// 
        private object options = new
        {
            language = "md", // 设置语法
            automaticLayout = true, // 高度自适应
            theme = "vs-dark", // 主题
        };
    
        private string fullName;
    
        protected override void OnInitialized()
        {
            _objRef = DotNetObjectReference.Create(this);
        }
    
        /// 
        /// 具体文件路径
        /// 
        [Parameter]
        [CascadingParameter(Name = nameof(FullName))]
        public string FullName
        {
            get => fullName;
            set
            {
                fullName = value;
                UpdateValue();
            }
        }
    
        /// 
        /// Monaco初始化事件
        /// 
        private async Task InitMonaco()
        {
            // 监听CTRL+S 2097 = CTRL+S 快捷键
            // 调用Monaco的Command,传递当前对象,并且指定当触发快捷键的时候调用当签对象的指定方法。
            await _editor.AddCommandAsync(2097, _objRef, nameof(SaveValue));
        }
    
        /// 
        /// 更新value
        /// 
        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();
        }
    
        /// 
        /// 更新文件内容
        /// 
        [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>FileEditorMToolbarTitle>
            <MButton OnClick="OpenFile">打开文件MButton>
            <MSpacer>MSpacer>
            <MButton Text Color="primary" Target="_blank" Href="https://docs.masastack.com/blazor/introduction/why-masa-blazor">AboutMButton>
        MAppBar>
    
        <MNavigationDrawer App @bind-Value="_drawer">
            <MList Nav Routable>
                <MListItem Href="/" ActiveClass="primary--text">
                    <MListItemIcon>
                        <MIcon>mdi-homeMIcon>
                    MListItemIcon>
                    <MListItemContent>
                        <MListItemTitle>HomeMListItemTitle>
                    MListItemContent>
                MListItem>
                <MListItem Href="/counter" ActiveClass="primary--text">
                    <MListItemIcon>
                        <MIcon>mdi-plusMIcon>
                    MListItemIcon>
                    <MListItemContent>
                        <MListItemTitle>CounterMListItemTitle>
                    MListItemContent>
                MListItem>
                <MListItem Href="/fetchdata" ActiveClass="primary--text">
                    <MListItemIcon>
                        <MIcon>mdi-list-boxMIcon>
                    MListItemIcon>
                    <MListItemContent>
                        <MListItemTitle>Fetch dataMListItemTitle>
                    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组件的绑定传递到内的所有子组件。

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

    技术交流

    qq群:452761192

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

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

  • 相关阅读:
    Valve下一代VR头显爆料汇总,看完有点期待
    思维导图:定时器设计
    ch579串口编程笔记
    Ansible相关
    深度神经网络算法有哪些,python深度神经网络算法
    云计算革命:多云管理与混合云的实践指南
    【数据结构与算法分析】0基础带你学数据结构与算法分析05--串 (string)
    消息队列这么多,用哪个哟?
    咖啡机、电热水壶、豆浆机上架亚马逊美国站UL1082认证标准
    使用applescript自动化trilium的数学公式环境(二)
  • 原文地址:https://www.cnblogs.com/hejiale010426/p/17671769.html