您当前的位置: 首页 >  c#

寒冰屋

暂无认证

  • 3浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

C# MVVM工具包演示

寒冰屋 发布时间:2022-09-20 19:30:00 ,浏览量:3

目录

介绍

背景

使用代码

MVVM结构/功能

这是内容的快速概述

安装MVVM工具包

MainWindow概念和代码

应用程序

Mod_Public

MVVM模式——详细信息

把事情放在一起——WPF概念和代码

QAT(快速访问工具栏)

依赖注入或服务注入

使用ISaveAsFileDlgVM保存文件对话框示例

Messenger 测试

PropertyChanged测试

事件触发器(EventTrigger)

可观察集合(ObservableCollection)

使用ObservableCollection进行测试

富文本(RichText)

结论

Credits / Reference

  • 下载源代码 - 7.1 MB

介绍

本文和演示是关于开始使用MVVM工具包和一些为MessageBox和一些对话框自创建的接口/服务。

背景

有许多关于其他MVVM框架的CodeProject文章,但几乎没有关于WPF和MVVM Toolkit的文章。所以我开始创建这个文档。

模型、视图和视图模型(MVVM模式)是组织或构建代码的 好方法,可帮助您简化、开发和测试(例如单元测试)应用程序。

模型保存数据, 与应用程序逻辑无关。

ViewModel 充当模型和视图之间的连接。

视图是用户界面。

我不会描述和解释完整演示项目的每一个细节。重点是如何测试一些特性。

使用代码 MVVM结构/功能

MVVM工具包来自Microsoft,并且其他一些使用的功能不是我自己的:来源在Credits/Reference部分中列出。

这是内容的快速概述
  • MVVM工具包和.NET 4.7.2
    • RelayCommand
    • OnPropertyChanged
    • ObservableRecipient(Messenger和ViewModelBase)
    • DependencyInjection(作为服务运行MsgBox和Dialog )
    • ObservableCollection(对于Credits Listbox)
  • Ribbon 菜单
  • 服务/对话框
  • 使用ICommand将按钮绑定到ViewModel
安装MVVM工具包

随着MVVM Toolkit的NuGet包的安装,它会安装6或7个其他包。

  • MVVM工具包简介——Windows社区工具MVVM工具包简介——Windows社区工具

 

对于DependencyInjection,我们需要安装另一个NuGet包:

 

我为MsgBox和一些对话框做了接口/服务。

DependencyInjection设法独立于viewmodel启动以下对话框:

  • FontDlgVM
  • MsgBoxService
  • DialogVM
  • OpenFileDlgVM
  • RibbonStatusService
  • SaveAsFileDlgVM
  • SearchDlgVM

这允许使用自定义Messagebox/对话框以及单元测试。

MainWindow概念和代码

MainWindow显示Ribbon。

在其下方有一个Tabcontrol, 带有用于MVVM工具包测试的选项卡和RichText。

类MainWindow背后的代码是:

{
    /// 
    /// Interaktionslogik für MainWindow.xaml
    /// 

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new TestingViewModel();
        }
    }
}

应用程序

注册服务/视图模型在后面的App代码中。

public partial class App : Application
    {
        private bool blnReady;
        public App()
        {
            InitializeComponent();
            Exit += (_, __) => OnClosing();
            Startup += Application_Startup;
            try
            {
                Mod_Public.sAppPath = Directory.GetCurrentDirectory();
                Ioc.Default.ConfigureServices(
                    new ServiceCollection()
                    .AddSingleton()
                    .AddSingleton((IDialog)new DialogVM())
                    .AddSingleton((IOpenFileDlgVM)new OpenFileDlgVM())
                    .AddSingleton((ISaveAsFileDlgVM)new SaveAsFileDlgVM())
                    .AddSingleton((IRichTextDlgVM)new RichTextDlgVM())
                    .BuildServiceProvider());
            }
            catch (Exception ex)
            {
                File.AppendAllText(Mod_Public.sAppPath + @"\Log.txt", 
                string.Format("{0}{1}", Environment.NewLine, 
                DateAndTime.Now.ToString() + "; " + ex.ToString()));
                var msgBoxService = Ioc.Default.GetService();
                msgBoxService.Show("Unexpected error:" + Constants.vbNewLine + 
                Constants.vbNewLine + ex.ToString(), img: MessageBoxImage.Error);
            }
        }
        private void OnClosing()
        {
        }
        private void Application_Startup(object sender, EventArgs e)
        {
            blnReady = true;
        }
   }

Mod_Public

Mod_Public包括:

public static void ErrHandler(string sErr)

和:

public static string ReadTextLines(string FileName)

MVVM模式——详细信息

从WPF Ribbon的角度来看,数据结构/模型很简单:

Ribbon有菜单项/ribbon按钮与ActiveRichTextBox或ActiveTextBox一起工作。

这就是我们在模型类中看到的TextData。

模型类称为TextData:

{
    public class TextData : ObservableRecipient, INotifyPropertyChanged
    {
        private string _text;
        private string _richText;
        private RibbonTextBox _NotifyTest;
        private string _readText;
        private TextBox _ActiveTextBox;
        private RichTextBox __ActiveRichTextBox;
        private RichTextBox _ActiveRichTextBox
        {
            [MethodImpl(MethodImplOptions.Synchronized)]
            get
            {
                return __ActiveRichTextBox;
            }
            [MethodImpl(MethodImplOptions.Synchronized)]
            set
            {
                __ActiveRichTextBox = value;
            }
        }
        private Ribbon _MyRibbonWPF;
        private MainWindow _MyMainWindow;
        public TextData()
        {
            //
        }
            public MainWindow MyMainWindow
        {
            get
            {
                return _MyMainWindow;
            }
            set
            {
                _MyMainWindow = (MainWindow)value;
            }
        }
        public Ribbon MyRibbonWPF
        {
            get
            {
                return _MyRibbonWPF;
            }
            set
            {
                _MyRibbonWPF = value;
            }
        }
        public RibbonTextBox NotifyTestbox
        {
            get
            {
                return _NotifyTest;
            }
            set
            {
                _NotifyTest = value;
            }
        }
        public string RichText
        {
            get
            {
                return _richText;
            }
            set
            {
                _richText = value;
                OnPropertyChanged("RichText");
            }
        }
        public string GetText
        {
            get
            {
                return _text;
            }
            set
            {
                _text = value;
                OnPropertyChanged("GetText");
            }
        }
        public string ReadText
        {
            get
            {
                return _readText;
            }
            set
            {
                _readText = value;
                GetText = _readText;
                OnPropertyChanged("ReadText");
            }
        }
        public TextBox ActiveTextBox
        {
            get
            {
                return _ActiveTextBox;
            }
            set
            {
                _ActiveTextBox = value;
                OnPropertyChanged("ActiveTextBox");
            }
        }
        public RichTextBox ActiveRichTextBox
        {
            get
            {
                return _ActiveRichTextBox;
            }
            set
            {
                _ActiveRichTextBox = value;
            }
        }
    }
}

ViewModel class叫TestingViewModel

名为TestingViewModel的类包含用于测试某些MVVM功能的属性ICommands和方法。它还包含ObservableCollection(Of Credits)的代码,该代码用于Listview本文的References / Credits部分。

把事情放在一起——WPF概念和代码 QAT(快速访问工具栏)

您可以从QAT中删除按钮(右键单击,会出现一个上下文菜单)。您可以在Ribbon下面显示QAT。您也可以从设置选项卡中恢复QAT。并且您可以更改Ribbon的backcolor。

依赖注入或服务注入

正如已经提到的,在应用程序的代码后面有一些代码。

使用ISaveAsFileDlgVM保存文件对话框示例

它使用interface ISaveAsFileDlgVM和service/ viewmodel SaveAsFileDlgVM。

public class TestingViewModel : ObservableRecipient, INotifyPropertyChanged

...    
       public ICommand SaveAsFileDlgCommand { get; set; }
...  
       RelayCommand cmdSAFD = new RelayCommand(SaveAsFileDialog);
       SaveAsFileDlgCommand = cmdSAFD;
...
        private void SaveAsFileDialog()
        {
            var dialog = Ioc.Default.GetService();
            if (ActiveRichTextBox is object)
            {
                dialog.SaveAsFileDlg(_textData.RichText, ActiveRichTextBox);
            }
            if (ActiveTextBox is object)
            {
                dialog.SaveAsFileDlg(_textData.GetText, ActiveTextBox);
            }
        }
...

而且,非常重要的是,Command="{Binding SaveAsFileDlgCommand}"/>在XAML文件中。

从Ribbon中,您可以启动和测试其他对话框或messagebox,以便:

  • 打开对话框
  • 搜索(来源在Credits/References中列出)
  • OpenFileDialog
  • 选项卡帮助 > 信息
  • FontDialog
Messenger 测试

添加Inherits ObservableRecipient很重要,这个和其他细节在ObservableObject - Windows Community Toolkit | 微软文档中有描述。

“视图特定消息应该在视图的Loaded事件中注册,并在Unloaded事件中注销,以防止内存泄漏和多次回调注册的问题。”

我们可以从Class TestingViewModel发送Msg:

Imports Microsoft.Toolkit.Mvvm.Messaging

    public class TestingViewModel : ObservableRecipient, INotifyPropertyChanged

private string msg;
…
_cmdMsg = new Command(SendMsgRibbonButton_Click);
…
        public ICommand SendMsg
        {
            get
            {
                return _cmdMsg;
            }
        }
…       

        private void SendMsgRibbonButton_Click()
        {
            try
            {
                // DataExchange / Messenger
                string msg = "Test Msg...";
                SetStatus("TestingViewModel", msg);
            }
            catch (Exception ex)
            {
                SetStatus("TestingViewModel", ex.ToString());
                Mod_Public.ErrHandler(ex.ToString());
            }
        }
...
        public void SetStatus(string r, string m)
        {
            try
            {
                Messenger.Send(new DialogMessage(m));
            }
            catch (Exception ex)
            {
                SetStatus("TestingViewModel", ex.ToString());
                Mod_Public.ErrHandler(ex.ToString());
            }
        }
...
public class StatusMessage
    {
        public StatusMessage(string status)
        {
            NewStatus = status;
        }
        public string NewStatus { get; set; }
    }

仅当消息已注册时Msg才可以发送:

using Microsoft.Toolkit.Mvvm.Messaging;
...
Messenger.Register(this, (r, m) => DialogMessage = m.NewStatus);
Messenger.Register(this, (r, m) => StatusBarMessage = m.NewStatus);
...
Messenger.Unregister(this);
Messenger.Unregister(this);

在关闭viewmodel时,我们必须注销该消息。

消息出现在StatusBar和Ribbon上。

PropertyChanged测试


两个textbox通常仅在activeTextbox与"RichText"或"PlainText"相关时显示。但是如果你手动编辑上面的,你可以看到下面的内容立即改变了。

这是由XAML文件中的UpdateSourceTrigger=PropertyChanged引起的。

事件触发器(EventTrigger)

要求:Microsoft.Xaml.Behaviors.Wpf(NuGet包)

xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
...
    
         
             
         
         
             
         
         
             
         
         
             
         
     
...

当Ribbon通过ContextMenu和其他东西最小化时使用它。

可观察集合(ObservableCollection)

它是viewmodel TestingViewModel的一部分,并用于Credits / References的listbox。

public class TestingViewModel : ObservableRecipient, INotifyPropertyChanged

#Region " fields"
...
private ObservableCollection _credit = new ObservableCollection();
...
#End Region
...
_credit = new ObservableCollection()
                {
                    new Credits()
                    {
                        Item = "MVVM Toolkit",
                        Note = "Microsoft",
                        Link = "https://docs.microsoft.com/en-us/windows/
                                communitytoolkit/mvvm/introduction"
                    },
                    new Credits()
                    {
                        Item = "MVVMLight",
                        Note = "GalaSoft",
                        Link = "https://www.codeproject.com/Articles/768427/
                                The-big-MVVM-Template"
                    },
                    new Credits()
                    {
                        Item = "ICommand with MVVM pattern",
                        Note = "CPOL",
                        Link = "https://www.codeproject.com/Articles/863671/
                                Using-ICommand-with-MVVM-pattern"
                    },
                    new Credits()
                    {
                        Item = "C# WPF WYSIWYG HTML Editor - CodeProject",
                        Note = "CPOL",
                        Link = "https://www.codeproject.com/Tips/870549/
                                Csharp-WPF-WYSIWYG-HTML-Editor"
                    },
                    new Credits()
                    {
                        Item = "SearchDialog",
                        Note = "Forum Msg",
                        Link = "https://social.msdn.microsoft.com/forums/vstudio/en-US/
                        fc46affc-9dc9-4a8f-b845-89a024b263bc/
                        how-to-find-and-replace-words-in-wpf-richtextbox"
                    }
               };
...
    public class Credits
    {
        public string Item { get; set; }
        public string Note { get; set; }
        public string Link { get; set; }
}

使用ObservableCollection进行测试

单击清除列表框以删除学分。

读取XML到Listbox以恢复引用。

ObservableCollection的优点是我们不需要Listbox的UpdateTrigger。

富文本(RichText)

从选项卡“RichText”中,您可以选择RichTextBox中的一些文本并使用RibbonButton对其进行格式化。其中许多是EditingCommand并且仅出现在UserCtlRibbonWPF.xaml文件中。

结论

这只是一个演示——它还没有准备好生产。

但我认为MVVM Toolkit将允许您进行各种扩展。

Credits / Reference
  • [1] Using ICommand with MVVM pattern - CodeProject
  • [2] Introduction to the MVVM Toolkit - Windows Community Toolkit | Microsoft Docs
  • [3] C# WPF WYSIWYG HTML Editor - CodeProject
  • [4] The big MVVM Template - CodeProject
  • [5] How to find and replace words in WPF richTextBox

https://www.codeproject.com/Articles/5332442/Csharp-MVVM-Toolkit-Demo

关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.0457s