C#中WPF实现依赖注入和MVVM,以及服务定位ServiceLocator

这篇具有很好参考价值的文章主要介绍了C#中WPF实现依赖注入和MVVM,以及服务定位ServiceLocator。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近在想重写架构于是就研究了一套WPF的相关内容,WPF不像MAUI内置了容器,需要我们自己手动添加,于是就有了今天的内容。

首先,我们新建一个.net6.0的WPF项目

  1. 由于WPF没有内置容器,我们先安装一下依赖注入的nuget包

Microsoft.Extensions.DependencyInjection

点开App.xaml文件,修改为如下

public partial class App : Application 
{
    /// <summary>
    /// Gets the current <see cref="App"/> instance in use
    /// </summary>
    public new static App Current => (App) Application.Current;
}
  1. 由于我们要使用服务定位模式,所以在主项目上添加一个ServiceLocator.cs类
public class ServiceLocator 
{
    private IServiceProvider _serviceProvider;

    public ServiceLocator() 
    {
        var serviceCollection = new ServiceCollection();

        _serviceProvider = serviceCollection.BuildServiceProvider();
    }
}

这时我们就使用了容器,等待类型注入,此时我们的依赖注入初步就完成了,下面进行添加MVVM模式

  1. 安装MVVVM的nuget包

CommunityToolkit.Mvvm

安装完成后,我们开始新建按照MVVM的规则的文件夹,便于我们以后分层
如下图所示
C#中WPF实现依赖注入和MVVM,以及服务定位ServiceLocator

  1. 在Models文件夹建一个Person类
public class Person 
{
    public int Id { get; set; } = 1;
    public string Name { get; set; } = "小米";
    
}

在ViewModels文件夹建一个MainWindowViewModel类

public class MainWindowViewModel : ObservableObject
{
    
}

使用MVVM模式的精髓就在于这个接口ObservableObject
MVVM的原理我们这里不做讲解,这里我们只讲怎么使用,优雅且自信
首先声明一下Person类

public partial class MainWindowViewModel : ObservableObject 
{
    [ObservableProperty]
    private Person _person;
}

这里的ObservableProperty实际帮我们自动写成了如下,并且class关键词前面要添加partial关键字,我们作为懒人肯定是不能写这么多的

private Person _person;
public Person Person {
    get => _person;
    set=> SetProperty(ref _person, value);
}

这时候我们出现了一个问题,这里我们要用依赖注入,那我们先去Service文件夹新建一个接口和实体类,我姑且叫做DataAccess
代码和结构如下图
C#中WPF实现依赖注入和MVVM,以及服务定位ServiceLocator

public class DataAccess : IDataAccess 
{
    public string GetData() => "我是xiaososa";
}

到了这里我们就应该想到既然我们写了服务类和ViewModel类,那我们顺便去注入一下,打开ServiceLocator.cs

public class ServiceLocator 
{
    private IServiceProvider _serviceProvider;

    public ServiceLocator() 
    {
        var serviceCollection = new ServiceCollection();

        serviceCollection.AddSingleton<IDataAccess, DataAccess>();

        serviceCollection.AddSingleton<MainWindowViewModel>();

        _serviceProvider = serviceCollection.BuildServiceProvider();
    }
}

这样我们就可以让MainWindowViewModel去依赖IDataAccess,回到MainWindowViewModel类进行依赖注入,并填写一个方法让我们的名字改变

public partial class MainWindowViewModel : ObservableObject 
{
    private int _num = 1;

    [ObservableProperty]
    private string _personName = $"Person类与我无瓜";

    [ObservableProperty]
    private Person _person;

    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(UpdateCommand))]
    private bool _isEnabled;

    private readonly IDataAccess _dataAccess;

    public MainWindowViewModel(IDataAccess dataAccess) 
    {
        Person = new Person();
        _dataAccess = dataAccess;
    }

    

    [RelayCommand(CanExecute = nameof(CanButtonClick))]
    public async Task UpdateAsync() 
    {
        await Task.Delay(500);
        PersonName = $"{_dataAccess.GetData()}=>{_num}";

        Person = new Person() {
            Name = _dataAccess.GetData(),
            Id = ++_num
        };

    }

    private bool CanButtonClick() => IsEnabled;
}

按照我们的预想结果,在勾选IsEnabledde时候我们点击button以后0.5秒后名字会改变,并且id自增,请注意RelayCommand
等同于我们在构造函数和声明内容如下

public MainWindowViewModel(IDataAccess dataAccess) 
    {
        _dataAccess = dataAccess;
        UpdateAsyncRelayCommand = new AsyncRelayCommand(UpdateAsync);
    }

public AsyncRelayCommand UpdateAsyncRelayCommand { get; }
  1. 接下来我们简单的添加几个控件在MainWindow.xaml页面上
<Window x:Class="WpfMVVMIOCServiceLocator.MainWindow"
        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:WpfMVVMIOCServiceLocator"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <Label Content="11111111111" FontSize="50" ></Label>
        <CheckBox Content="IsEnabled"  FontSize="30" HorizontalAlignment="Center"></CheckBox>
        <Label Content="Person类雨我无瓜" FontSize="50" HorizontalAlignment="Center" />
        <Button FontSize="25" Content="我是一个按钮" BorderBrush="Black" BorderThickness="2" Margin="10,10,10,10" HorizontalAlignment="Center" Command="{Binding ShowCommand}" />
    </StackPanel>
</Window>

效果如下
C#中WPF实现依赖注入和MVVM,以及服务定位ServiceLocator

这时候我们就要运用ServicesLocator和MVVM模式,改变他们的显示
让我们先打开ServiceLocator.cs,因为之前我们已经注入过ViewModel了,现在我们声明公开一下MainWindowViewModel
代码如下,添加一个

public MainWindowViewModel? MainWindowViewModel => _serviceProvider.GetService();

private IServiceProvider _serviceProvider;

public MainWindowViewModel? MainWindowViewModel => _serviceProvider.GetService<MainWindowViewModel>();

public ServiceLocator() 
{
     var serviceCollection = new ServiceCollection();

     serviceCollection.AddSingleton<IDataAccess, DataAccess>();

     serviceCollection.AddSingleton<MainWindowViewModel>();

     _serviceProvider = serviceCollection.BuildServiceProvider();
 }

优雅的地方来了,这是我们能在Xaml文件下提示感知的关键,让我们先打开App.xaml,添加一下Resources

<Application x:Class="WpfMVVMIOCServiceLocator.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfMVVMIOCServiceLocator"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <local:ServiceLocator x:Key="ServiceLocator"/>
        </ResourceDictionary>
    </Application.Resources>
</Application>

然后回到MainWindow.xaml,在Window处添加

DataContext=“{Binding MainWindowViewModel,Source={StaticResource ServiceLocator}}”

这里有一个优雅的写法,当你写到DataContext="{Binding的时候,先按一下空格,然后写一个逗号,在写Source={StaticResource ServiceLocator}}”,后面就可以自动感知到MainWindowViewModel

C#中WPF实现依赖注入和MVVM,以及服务定位ServiceLocator

好了,这次我们就可以绑定值了,将刚才的控件都修改一下,mode我们选择双向绑定,意味着只要值有变化就会通知前台更改值

<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
    <Label Content="{Binding Person.Name,Mode=TwoWay}" FontSize="50" HorizontalAlignment="Center" />
    <CheckBox Content="IsEnabled" IsChecked="{Binding IsEnabled}" FontSize="30" HorizontalAlignment="Center"></CheckBox>
    <Label Content="{Binding PersonName,Mode=TwoWay}" FontSize="50" HorizontalAlignment="Center" />
    <Button FontSize="25" Content="{Binding Person.Id,Mode=TwoWay}" Width="200" BorderBrush="Black" BorderThickness="2" Margin="10,10,10,10" HorizontalAlignment="Center" Command="{Binding UpdateCommand}" />
</StackPanel>

然后让我们启动,这下我们的IOC_MVVM_ServiceLocator就建立好了,需要勾选IsEnabled才可以点击button
效果如下,button按钮的名字总是要比上面多1的,那我们的效果就达到了
C#中WPF实现依赖注入和MVVM,以及服务定位ServiceLocator
好的,我们这次示例就到此为止了,
还有个很严重的问题,假如你们引入MVVM包和依赖注入包会报这个乱码错误蟹变露Exception.ToString0 奸姝楷板窜稿纺人覆?,不是你们的问题,是IDE的锅,建议重新安装组件或者升级,正常情况下是不冲突的
C#中WPF实现依赖注入和MVVM,以及服务定位ServiceLocator
有小伙伴不明白的可以参考以下视频
MVVM:【用 CommunityToolkit.Mvvm 加速 MVVM 开发流程】https://www.bilibili.com/video/BV12x4y177qB?vd_source=b2be7496dbe636cb228643582ce2c4b3
依赖注入:【.NET 6 中 WPF 的依赖注入,包括工厂模式】https://www.bilibili.com/video/BV18V4y177TY?vd_source=b2be7496dbe636cb228643582ce2c4b3
ServiceLocator:【.NET MAUI HelloWorld Part 2】https://www.bilibili.com/video/BV1Gt4y177zA?vd_source=b2be7496dbe636cb228643582ce2c4b3
文章来源地址https://www.toymoban.com/news/detail-443092.html

到了这里,关于C#中WPF实现依赖注入和MVVM,以及服务定位ServiceLocator的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • WPF Prism MVVM技巧【用注入方式在不同项目中访问主窗体(MainWindow)】

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目的是想在Prism MVVM中通过注入的方式来全局访问主窗体(MainWindow)。 创建一个Prism Full App(WPF)项目,在Services项目文件夹中创建一个Public_Global项目并创建一个Global.cs类用来注入。 Dongming_BigTest.App.xmal.c

    2024年02月05日
    浏览(40)
  • C# WPF简单的MVVM模式事例

    WPF中使用MVVM模式开发有诸如以下优点: 1.结构清晰明朗,上手成本低,一个新人也能快速的定位自己需要改动代码的位置。 2.耦合度低,更改WPF控件不影响数据结构,更改代码成本低。 3.可重用性高,比如一个处理逻辑放到ViewModel模块中,其他界面如果要用掉直接调用即可。

    2024年02月09日
    浏览(47)
  • WPF使用依赖注入

    现在依赖注入在.Net里面已经普及,自己常写一些简单的demo倒是无所谓,但偶尔写一点正式的工程,也免不了要使用一下,于是总结了一下在WPF里面使用依赖注入。 在写简单Demo时候,通常是在MainWindow的构造函数里面直接做初始化,各种变量也都丢在MainWindow类里面。在使用依

    2024年02月11日
    浏览(33)
  • WPF 用户控件依赖注入赋值

    我一直想组件化得去开发WPF,因为我觉得将复杂问题简单化是最好的 cs部分 我将复杂的依赖注入的代码进行了优化,减少了重复内容的输入。 我现在依赖属性扩展封装在一个静态文件里面 记得UserControl.xaml里面绑定你ViewModel。这样的话有代码提示 我后面要根据Vue的单向数据

    2024年02月07日
    浏览(44)
  • 深入理解WPF中的依赖注入和控制反转

    在WPF开发中, 依赖注入(Dependency Injection)和控制反转(Inversion of Control)是程序解耦的关键,在当今软件工程中占有举足轻重的地位,两者之间有着密不可分的联系 。今天就以一个简单的小例子,简述如何在WPF中实现依赖注入和控制反转,仅供学习分享使用,如有不足之处

    2024年02月06日
    浏览(48)
  • c#依赖注入

    依赖注入(Dependency Injection,简称 DI)是一种设计模式,用于将对象的创建和管理责任从使用它的类中分离出来,从而实现松耦合和易于测试的代码。在 C# 中,依赖注入通常通过以下方式实现: 构造函数注入(Constructor Injection): 这是最常见的依赖注入方式,通过类的构造

    2024年02月12日
    浏览(37)
  • C# Blazor 学习笔记(10):依赖注入

    Blazor 具有前后端不分离模式,但是如何直接调用需要一定的设置 依赖注入在spring里面很常见,毕竟.NET 是个巨型融合怪。只要你这个好用我就抄。我还是很佩服的,能实现就行,谁管是谁第一个开发的。MVVM还是WPF首创的呢,Vue用也没关系。能简化程序员逻辑就行。 依赖注入

    2024年02月14日
    浏览(38)
  • WPF 如何实现事件绑定 (MVVM)

    首先说到绑定,一般是在WPF 中常见的,因为WPF中有一个比较好用的框架叫做 MVVM 所以View层的按钮等元件的的动作都是需要和后台ViewModel 中的函数进行绑定的。 如 我们最常见的按钮的command 绑定 这里面的command 是命令,不是事件 如果点击图片,或者按钮抬起来的时候需要触

    2024年02月04日
    浏览(52)
  • 【C#】.net core 6.0 依赖注入生命周期

    给自己一个目标,然后坚持一段时间,总会有收获和感悟! 对于.net core而言,依赖注入生命周期有三种瞬态(Transient)、作用域(Scoped)和单例(Singleton),无论使用哪种生命周期,都需要确保对象的线程安全性,并正确地处理依赖关系。 在了解依赖注入的生命周期前,我

    2024年02月03日
    浏览(49)
  • WPF MVVM之INotifyPropertyChanged接口的几种实现方式

    序言        借助WPF/Sliverlight强大的数据绑定功能,可以比实现比MFC,WinForm更加优雅轻松的数据绑定。但是在使用WPF/Silverlight绑定时,有件事情是很苦恼的:当ViewModel对象放生改变,需要通知UI。我们可以让VM对象实现INotifyPropertyChanged接口,通过事件来通知UI。但问题就出现

    2024年02月16日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包