WPF MVVM进阶系列教程(一、对话框)

🍠 WPF MVVM进阶系列教程

  • 一、对话框

在前面的文章中,我们介绍了MVVM开发的一些基础知识。

对于日常开发来说,基本已经足够应付大部分场景。

从这里开始,介绍的都是在MVVM模式开发中,提升程序可维护性、灵活性、健壮性等方面的技巧。

包括对话框单元测试数据验证Ioc数据访问三方MVVM框架使用等。

可以根据自身学习情况阅读。

Dialog

在WPF中,我们经常会用到对话框,包括非模态(Show())模态(ShowDialog())两种。

在基于Code-Behind模式的开发中,我们一般会直接在逻辑代码中,直接操作对话框。

类似下面这样

消息框

1         private void Button_Click(object sender, RoutedEventArgs e)
2         {
3             System.Windows.MessageBox.Show("HelloWorld");
4         }

自定义对话框

1         private void Button_Click(object sender, RoutedEventArgs e)
2         {
3             MyDialogWindow dialog = new MyDialogWindow();
4             MyDialogWindow.DataContext = new MyDialogWindowViewModel();
5             MyDialogWindow.Owner = Application.Current.MainWindow;
6             dialog.Show();
7         }

但在MVVM模式中,不建议使用这种直接去操作对话框的方式。

主要考虑以下几个因素

1、直接调用 Show() 或 ShowDialog() 需要ViewModel引用System.Windows。这就打破了 MVVM 所期望的关注点分离,使测试代码等工作变得更加困难。

2、另一个问题与对话框的所有权(Owner)有关,因为我们需要设置对话框的父窗口,但显然在ViewModel中无法做到。即使我们直接从ViewModel中显示对话框,也无法直接从ViewModel中设置所有者,除非我们从View中引用ViewModel。

3、不利于模块化和代码重用,如果将对话框做成独立的模块,可以更方便移植。

4、不利于单元测试。

接下来我们就来看看如何使用DialogService来规避这些问题

使用DialogService

DialogService(对话框服务)是一种使用抽象层来显示对话框的方法。

ViewModel将显示对话框的责任委托给DialogService,只需向服务提供显示所需的数据即可。

DialogService拥有显示对话框的职责,因此我们可以将ViewModel与 System.Windows解耦,避免从ViewViewModel之间的引用。

在单元测试中,我们可以注入一个虚假的对话框服务实例,而不是显示实际的对话框,并使用我们的虚假对象进行预留和模拟。

说明:因为目前我们还没有使用Ioc容器,所以需要手动创建DialogService实例,并声明为单例模式,且不能通过注入的形式进行调用。

在后面会介绍如何在MVVM模式中使用Ioc。使用Ioc容器后,容器会帮我们完成这个操作。 

不过使用Ioc容器不是必须的,手动操作也可以达到同样的功能。

使用DialogService的MessageBox示例

1、定义DialogService的接口

IDialogService.cs

在这个对话框服务的接口中,我们定义了一个显示消息的接口。

1     public interface IDialogService
2     {
3         MessageBoxResult ShowMessage(string title, string content);
4     }

说明:为了方便演示,该示例中还是使用了System.WIndows.MessageBox及相关类型。

2、定义DialogService的实现

因为我们目前还没有使用Ioc容器,所以我们将DialogService类型定义成单例模式。

DialogService.cs

 1  public class DialogService : IDialogService2  {3      private static volatile DialogService instance;4      private static object obj = new object();5 6      /// <summary>7      /// 单例模式8      /// </summary>9      public static DialogService Instance
10      {
11          get
12          {       
13              if(instance == null)
14              {
15                  lock(obj)
16                  {
17                      if (instance == null)
18                          instance = new DialogService();
19                  }
20              }  
21 
22              return instance;
23          }
24      }
25 
26      /// <summary>
27      /// ShowMessage接口实现
28      /// </summary>
29      /// <param name="title"></param>
30      /// <param name="content"></param>
31      /// <returns></returns>
32      public MessageBoxResult ShowMessage(string title, string content)
33      {
34          return MessageBox.Show(title, content);
35      }
36  }

3、定义主界面

在界面上放置一个按钮,当按钮点击时,弹出对话框

MainWindow.xaml

1 <Window x:Class="_1_DialogService.MainWindow"
2         Title="MainWindow" Height="450" Width="800">
3     <Grid>
4         <Button Content="ShowMessage" Width="88" Height="28" Command="{Binding ShowMessageCommand}"></Button>
5     </Grid>
6 </Window>

4、定义主界面ViewModel并绑定到DataContext

MainWindowViewModel.cs

 1     public class MainWindowViewModel2     {3         /// <summary>4         /// DialogService实例5         /// </summary>6         private IDialogService dialogService;7 8         public ICommand ShowMessageCommand { get; set; }9 
10         public MainWindowViewModel()
11         {
12             ShowMessageCommand = new RelayCommand(ShowMessage);
13 
14             //如果通过注入的形式,可以我们从构造函数取得IDialogService的实例
15             //这里我们手动获取
16             this.dialogService = DialogService.DialogService.GetInstance();
17         }
18 
19         private void ShowMessage()
20         {
21             var result = this.dialogService.ShowMessage("标题", "内容");
22         }
23     }

运行效果如下:

这样我们就拥有了一个基于DialogService的最简单的实践示例。

这种情况对于普通消息框都可以应付。

基于DialogService的复杂对话框示例

前面的示例中,我们演示了使用DialogService对普通 的消息框进行操作。

但是如果我们需要显示一个复杂的数据对话框,应该如何去操作呢?

这里就需要借助数据模板的相关功能。

在《TabControl绑定到列表并单独指定每一页内容》,文章中,介绍过如何通过数据模板功能将ViewModel和View绑定起来。

假设我们有一个Student列表,Student具备Id、Name、Age三个属性,当在界面选择列表项后,单击显示详情按钮,使用对话框显示Student的详细信息。

1、定义StudentViewModel

StudentViewModel.cs

StudentViewModel内部定义了IdNameAge三个属性。

日常使用时,它内部可能会有更复杂的逻辑,这里我们只定义简单的数据进行演示。

 1   public class StudentViewModel : INotifyPropertyChanged2   {3       public event PropertyChangedEventHandler? PropertyChanged;4 5       private int id;6 7       private string name;8 9       private string age;
10 
11       public int Id
12       {
13           get => id;
14           set
15           {
16               id = value;
17               PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Id"));
18           }
19       }
20 
21       public string Name
22       {
23           get => name;
24           set
25           {
26               name = value;
27               PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
28           }
29       }
30 
31       public string Age
32       {
33           get => age;
34           set
35           {
36               age = value;
37               PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Age"));
38           }
39       }
40   }

2、定义IDialogService接口

IDialogService.cs

1   public interface IDialogService
2   {
3       void ShowStudentDetail(StudentViewModel student);
4   }

这里我们暂时先不做接口的实现,等后面的准备工作都完成了再去实现这个接口。

3、定义对话框窗口

因为我们要将ViewModelView绑定,所以这个对话框窗口并不是实际要显示的内容,它只是一个“壳”。

在窗口里放置一个ContentControl,并使用自动绑定,用于内容显示

DialogView.xaml

1 <Window x:Class="_2_DialogServiceShowDetail.Views.DialogView"
2         mc:Ignorable="d"
3         Title="DialogView" Height="450" Width="800">
4     <Grid>
5         <ContentControl Content="{Binding}"></ContentControl>
6     </Grid>
7 </Window>

4、定义数据展示界面

有了前面的DialogView窗口后,我们可以增加一个UserControl,用于实际数据显示

StudentView.xaml

StudentView内部绑定到StudentViewModel对应的属性

 1 <UserControl x:Class="_2_DialogServiceShowDetail.Views.StudentView"2              d:DesignHeight="450" d:DesignWidth="800">3     <Grid>4         <Grid.ColumnDefinitions>5             <ColumnDefinition/>6             <ColumnDefinition/>7         </Grid.ColumnDefinitions>8 9         <Grid.RowDefinitions>
10             <RowDefinition/>
11             <RowDefinition/>
12             <RowDefinition/>
13         </Grid.RowDefinitions>
14 
15         <Label Content="Id" HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Center"/>
16         <TextBox Grid.Column="1" Text="{Binding Id}" VerticalAlignment="Center" Margin="10,0"></TextBox>
17 
18         <Label Grid.Row="1" Content="Name" HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Center"/>
19         <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Name}" VerticalAlignment="Center" Margin="10,0"></TextBox>
20 
21         <Label Grid.Row="2" Content="Age" HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Center"/>
22         <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Age}" VerticalAlignment="Center" Margin="10,0"></TextBox>
23     </Grid>
24 </UserControl>

大概效果如下

4、定义View和ViewModel的映射 

这里我们借助数据模板功能,实现StudentViewModel和StudentView的映射

增加一个资源字典

DialogTemplate.xaml

1 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3                     xmlns:vm="clr-namespace:_2_DialogServiceShowDetail.ViewModels"
4                     xmlns:view="clr-namespace:_2_DialogServiceShowDetail.Views">
5     <DataTemplate DataType="{x:Type vm:StudentViewModel}">
6         <view:StudentView />
7     </DataTemplate>
8 </ResourceDictionary>

5、在App.xaml中使用资源字典

1  <Application.Resources>
2      <ResourceDictionary>
3          <ResourceDictionary.MergedDictionaries>
4              <ResourceDictionary Source="DialogTemplate.xaml"></ResourceDictionary>
5          </ResourceDictionary.MergedDictionaries>
6      </ResourceDictionary>
7  </Application.Resources>

说明:我们可以直接将这个数据模板定义在App.xaml里面,DialogTemplate.xaml这个资源字典不是必须的。

新建资源字典文件再引入的原因是使项目结构更清晰,更容易查找 。

6、实现IDialogService接口

在这里我们就可以实现IDialogService接口了,在显示对话框时,只需要将StudentViewModel传递到DialogView的数据上下文,DialogView就会自动加载StudentViewDialogView中显示。

DialogService.cs

 1  public class DialogService : IDialogService2  {3      private static volatile DialogService instance;4      private static object obj = new object();5 6      /// <summary>7      /// 单例模式8      /// </summary>9      public static DialogService GetInstance()
10      {
11          if (instance == null)
12          {
13              lock (obj)
14              {
15                  if (instance == null)
16                      instance = new DialogService();
17              }
18          }
19 
20          return instance;
21      }
22 
23      //显示对话框
24      public void ShowStudentDetail(StudentViewModel studentViewModel)
25      {
26          //设置StudentViewModel到DialogView的数据上下文
27          //DialogView会自动加载StudentView
28          var dialog = new DialogView() { DataContext = studentViewModel };
29          dialog.Owner = Application.Current.MainWindow;
30          dialog.ShowInTaskbar = false;
31          dialog.ShowDialog();
32 
33      }
34  }

7、定义主界面

在主界面中放置一个ListBoxButton,当点击Button时,弹窗显示选中项的详情。

MainWindow.xaml

 1 <Window x:Class="_2_DialogServiceShowDetail.MainWindow"2         Title="MainWindow" TitleVisibility="Collapsed" Height="400" Width="300" MinimizeVisibility="Collapsed" MaximizeVisibility="Collapsed" WindowStartupLocation="CenterScreen">3     <tianxia:BlurWindow.Background>4         <SolidColorBrush Color="White" Opacity=".9"></SolidColorBrush>5     </tianxia:BlurWindow.Background>6     <Grid>7         <Grid.RowDefinitions>8             <RowDefinition/>9             <RowDefinition Height="35"/>
10         </Grid.RowDefinitions>
11 
12         <ListBox ItemsSource="{Binding StudentList}" SelectedIndex="{Binding StudentListSelectedIndex}" BorderThickness="0" DisplayMemberPath="Name"></ListBox>
13 
14         <Button Content="显示详情" Width="88" Height="28" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="1" Command="{Binding ShowStudentDetailCommand}"></Button>
15     </Grid>
16 </Window>

8、定义主界面ViewModel并绑定到DataContext

MainWindowViewModel.cs

MainWindowViewModel中定义描述如下:

StudentList:用于绑定到列表显示。

StudentListSelectedIndex:用于绑定到列表选中索引。

ShowStudentDetailCommand:显示详情命令,绑定到显示详情按钮上

IDialogService:对话框服务接口,通过DialogService单例获取实例。

 1 public class MainWindowViewModel : INotifyPropertyChanged2 {3     private IDialogService dialogService;4 5     private ObservableCollection<StudentViewModel> studentList = new ObservableCollection<StudentViewModel>();6 7     public ObservableCollection<StudentViewModel> StudentList8     {9         get => studentList;
10         set
11         {
12             studentList = value;
13             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("StudentList"));
14         }
15     }
16 
17     private int studentListSelectedIndex = -1;
18 
19     public int StudentListSelectedIndex
20     {
21         get => studentListSelectedIndex;
22         set
23         {
24             studentListSelectedIndex = value;
25             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("StudentListSelectedIndex"));
26         }
27     }
28 
29 
30     public ICommand ShowStudentDetailCommand { get; private set; }
31 
32     public event PropertyChangedEventHandler? PropertyChanged;
33 
34     public MainWindowViewModel()
35     {
36         dialogService = DialogService.DialogService.GetInstance();
37 
38         ShowStudentDetailCommand = new RelayCommand(ShowStudentDetail);
39 
40         StudentList.Add(new StudentViewModel() { Id = 1,Name  = "测试1",Age = "17"});
41         StudentList.Add(new StudentViewModel() { Id = 2, Name = "测试2", Age = "18" });
42         StudentList.Add(new StudentViewModel() { Id = 3, Name = "测试3", Age = "19" });
43     }
44 
45     private void ShowStudentDetail()
46     {
47         dialogService.ShowStudentDetail(StudentList[StudentListSelectedIndex]);
48     }
49 }

运行效果如下:

手动关闭对话框并获取对话框结果

通过上述两个示例,我们对DialogService已经有了较为深入的认识。

但是现在还存在一个关键问题没有解决,就是如何关闭对话框,并获取对话框结果

接下来我们讲解一下如何在DialogService的基础上,实现关闭对话框并获取对话框结果。

在过去,我们一般会使用类似下面的代码结构来获取对话框的结果

 1  var dialogResult = System.Windows.MessageBox.Show("是否确认", "标题", System.Windows.MessageBoxButton.YesNoCancel, System.Windows.MessageBoxImage.Information);2 3  if(dialogResult == System.Windows.MessageBoxResult.Yes)4  {5      //是6  }7  else if(dialogResult == System.Windows.MessageBoxResult.No)8  {9      //否
10  }
11  else
12  {
13      //取消
14  }

但是使用了DialogService后,我们不会直接操作对话框窗口,应该如何实现呢?

先说一下大概实现思路

1、给DialogViewModel里增加一个事件,当在Dialog上点击相应的按钮时,引发这个事件

2、将界面点击的结果以参数形式传到事件,例如点击确认时传递Ok

3、在DialogService内部创建DialogViewViewModel时,为这个事件添加处理程序

4、事件处理程序内部负责关闭对话框,并获取结果供下一步调用。

5、封装DialogService时,传入一个回调,当对话框关闭时,将获取的对话框结果通过这个回调传出去。

简单点来说,就是在DialogService里创建对话框时,创建一个回调,让对话框通过回调的形式来操作对话框的关闭并返回结果。

实现步骤

1、定义对话框结果枚举

DialogResult.cs

1     public enum DialogResult
2     {
3         Ok,
4         Cancel
5     }

2、创建封装DialogViewModel内部事件的接口

IMyDialog.cs

1     public interface IMyDialog
2     {
3         event Action<DialogResult> RequestClose;
4     }

3、创建DialogView

这个是用于显示对话框的壳

DialogView.xaml

1 <Window x:Class="_3_DialogResult.Views.DialogView"
2         Title="DialogView" Height="280" Width="350" WindowStartupLocation="CenterScreen">
3     <Grid>
4         <ContentControl Content="{Binding}"></ContentControl>
5     </Grid>
6 </Window>

4、创建对话框内容

NotificationDialog.xaml

这里我们放置了两个按钮,OkCancel

当点击Ok时执行OkCommand

当点击Cancel时执行CancelCommand

 1 <UserControl x:Class="_3_DialogResult.Views.NotificationDialog"2              d:DesignHeight="450" d:DesignWidth="800">3     <Grid x:Name="LayoutRoot" Margin="5">4         <Grid.RowDefinitions>5             <RowDefinition />6             <RowDefinition Height="Auto" />7         </Grid.RowDefinitions>8 9         <TextBlock Text="Hello World" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="50" Grid.Row="0" TextWrapping="Wrap" />
10         <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0" Grid.Row="1" >
11             <Button Command="{Binding OkCommand}" Content="OK" Width="75" Height="25" IsDefault="True" />
12             <Button Command="{Binding CancelCommand}" Content="Cancel" Width="75" Height="25" Margin="10,0,0,0" IsCancel="True" />
13         </StackPanel>
14     </Grid>
15 </UserControl>

5、创建对话框ViewModel

当点击Ok/Cancel按钮时,引发IMyDialog里的RequestClose事件。

NotificationDialogViewModel.cs

 1  public class NotificationDialogViewModel : IMyDialog2  {3      public ICommand OkCommand { get; private set; }4 5      public ICommand CancelCommand { get; private set; }6 7      public NotificationDialogViewModel()8      {9          OkCommand = new RelayCommand(Ok);
10          CancelCommand = new RelayCommand(Cancel);
11      }
12 
13      public event Action<DialogResult> RequestClose;
14 
15      private void Cancel()
16      {
17          RaiseRequestClose(DialogResult.Cancel);
18      }
19 
20      private void Ok()
21      {
22          RaiseRequestClose(DialogResult.Ok);
23      }
24 
25      private void RaiseRequestClose(DialogResult dialogResult)
26      {
27          RequestClose?.Invoke(dialogResult);
28      }  
29  }

6、创建IDialogService

在显示对应框时,传入一个回调Action<DialogResult> resultCallback,这个回调会在对话框关闭时调用,并返回对话框结果

1    public interface IDialogService
2    {
3        void ShowNotificationDialog(Action<DialogResult> resultCallback);
4    }

7、创建DialogService

这里我们可以看到,在创建NotificationDialogViewModel时,我们为IMyDialog.RequestClose事件增加了一个事件处理程序。

这个事件处理程序里有如下逻辑:

1、获取了对话框结果

2、然后关闭对话框

3、调用IDialogService创建对话框时传进来的回调,通知外部对话框已经关闭,并传回对话框结果

 1  public class DialogService : IDialogService2  {3      4      public void ShowNotificationDialog(Action<DialogResult> resultCallback)5      {6          DialogResult dialogResult;7          var dialog = new DialogView();8 9          NotificationDialogViewModel notificationDialogViewModel = new NotificationDialogViewModel();
10          notificationDialogViewModel.RequestClose += (x)=> 
11          {
12              dialogResult = x;
13              dialog.Close();
14              resultCallback?.Invoke(dialogResult);
15          };
16 
17          dialog.ShowInTaskbar = false;
18          dialog.DataContext = notificationDialogViewModel;
19          dialog.ShowDialog();
20      }
21  }

其它部分的代码暂时就省略了,可以到示例代码中进行查看。

运行效果如下:

说明:这里只是展示原理,正式使用时,可以根据实际使用情况进行优化。

示例代码

https://github.com/zhaotianff/WPF-MVVM-Beginner/tree/main/7_Dialog

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/79754.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AI News | 20250507】每日AI进展

AI Repos 1、CFWorkerACME SSL证书助手是一个免费开源的平台&#xff0c;基于Cloudflare Worker运行&#xff0c;旨在自动化SSL证书的申请和下发&#xff0c;尤其适用于多服务器或内网环境。它通过自动化的CNAME和DNS操作完成域名验证&#xff0c;支持Let’s Encrypt、ZeroSSL…

5 分钟用满血 DeepSeek R1 搭建个人 AI 知识库(含本地部署)

最近很多朋友都在问:怎么本地部署 DeepSeek 搭建个人知识库。 老实说,如果你不是为了研究技术,或者确实需要保护涉密数据,我真不建议去折腾本地部署。 为什么呢? 目前 Ollama 从 1.5B 到 70B 都只是把 R1 的推理能力提炼到 Qwen 和 Llama 的蒸馏版本上。 虽说性能是提升…

极狐GitLab 分支管理功能介绍

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 分支 (BASIC ALL) 分支是项目工作树的一个版本。分支是项目开发的基础。当你创建一个新的项目时&#xff0c;极狐GitLab 会为…

基于ASP.NET+MySQL实现待办任务清单系统

基于ASP.NET的ToDoList的设计与实现 一、前言 1.1 实验目的 使学生综合使用所学过的ASP.NET网络编程知识&#xff0c;掌握网络环境程序设计的基本概念&#xff1b;结合实际的操作和设计&#xff0c;巩固课堂学习内容&#xff0c;掌握网络环境编程的特点、原理和技术&#xf…

普通 html 项目引入 tailwindcss

项目根目录安装依赖 npm install -D tailwindcss3 postcss autoprefixer 初始化生成tailwind.config.js npx tailwindcss init 修改tailwind.config.js /** type {import(tailwindcss).Config} */ module.exports {content: ["./index.html"], //根据自己的项目…

汽车免拆诊断案例 | 2015款奔驰C200L车发动机起动延迟

故障现象  一辆2015款奔驰C200L车&#xff0c;搭载274发动机&#xff0c;累计行驶里程约为15.6万km。该车发动机起动延迟&#xff0c;且发动机故障灯异常点亮。 故障诊断  用故障检测仪检测&#xff0c;发动机控制单元中存储有故障代码“P001685 进气凸轮轴&#xff08;气缸…

[蓝桥杯 2025 省 B] 水质检测(暴力 )

暴力暴力 菜鸟第一次写题解&#xff0c;多多包涵&#xff01;&#xff01;! 这个题目的数据量很小&#xff0c;所以没必要去使用bfs&#xff0c;直接分情况讨论即可 一共两排数据&#xff0c;我们使用贪心的思想&#xff0c;只需要实现从左往右的过程中每个检测器相互连接即…

网络接口返回类ResponseEntity

网络接口返回类ResponseEntity 简介方法获取工厂方法ResponseEntity.ok()返回BodyBuilder返回文字信息返回类对象&#xff08;Spring自动转换为json格式&#xff09;返回空内容‌ ResponseEntity.notFound()返回HeadersBuilder返回文字信息 status(HttpStatus)返回BodyBuildern…

Redis:现代服务端开发的缓存基石与电商实践-优雅草卓伊凡

Redis&#xff1a;现代服务端开发的缓存基石与电商实践-优雅草卓伊凡 一、Redis的本质与核心价值 1.1 Redis的技术定位 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的内存数据结构存储系统&#xff0c;由Salvatore Sanfilippo于2009年创建。它不同于传…

macOS上管理多个Node.js版本

管理工具 fnm 和 nvm nvm&#xff1a;作为最广泛使用的 Node.js 版本管理器&#xff0c;使用 Bash 编写&#xff0c;适用于类 UNIX 环境(如 macOS 和 Linux)&#xff0c;也可以通过兼容的 shell(如 WSL)在 Windows 上使用。fnm&#xff1a;(Fast Node Manager)一种较新的、快速…

uDistil-Whisper:低数据场景下基于无标签数据过滤的知识蒸馏方法

uDistil-Whisper: Label-Free Data Filtering for Knowledge Distillation in Low-Data Regimes 会议&#xff1a;2025年NAACL 机构&#xff1a;卡内基梅降大学 Abstract 近期研究通过伪标签&#xff08;pseudo-labels&#xff09;将Whisper的知识蒸馏到小模型中&#xff0…

【MySQL】-- 数据库约束

文章目录 1. 什么是数据库约束2. 约束类型3. NOT NULL 非空约束4. DEFALUT 默认值约束5. UNIQUE 唯一约束6. PRIMARY KEY 主键约束6.1 自增主键6.1 一个自增主键包含多个列 7. FOREIGN KEY 外键约束8. CHECK 约束 1. 什么是数据库约束 数据库约束是指对数据库表中的数据所施加…

鸿蒙NEXT开发动画案例2

1.创建空白项目 2.Page文件夹下面新建Spin.ets文件&#xff0c;代码如下&#xff1a; // 接口定义&#xff08;必须放在使用前&#xff09; /*** 关键帧动画整体配置参数*/ interface KeyframeAnimationConfig {iterations: number;delay: number; }/*** 单个关键帧动画项*/…

团队协作的润滑剂——GitHub与协作流程

各位代码界的社交恐惧症患者们&#xff0c;今天我们要聊的是如何假装自己很会团队协作——使用GitHub&#xff01;这就像程序员版的"相亲平台"&#xff0c;只不过在这里&#xff0c;你展示的不是自拍和收入&#xff0c;而是代码和commit记录&#xff08;后者往往更令…

「Mac畅玩AIGC与多模态13」开发篇09 - 基于多插件协同开发智能体应用(天气+名言查询助手)

一、概述 本篇介绍如何在 macOS 环境下&#xff0c;同时接入多个自定义 OpenAPI 插件&#xff0c;实现智能体根据用户请求自动分析&#xff0c;调用天气查询或名言查询服务&#xff0c;完成多功能协同应用开发。 二、环境准备 1. 确认本地开发环境 macOS 系统Dify 平台已部…

react-12父子组件间的数据传递(子传父)(父传子)- props实现

1.子组件调用父组件的函数并传递数据&#xff08;子传父&#xff09; 1.1父组件 import React, { Component } from react; import ChildComponent from ./ChildComponent;class ParentComponent extends Component {constructor(props) {super(props);this.state {items: […

Spring Boot 单元测试使用教程(仅供参考)

单元测试是软件开发中至关重要的一环&#xff0c;Spring Boot 提供了强大的测试支持。以下是 Spring Boot 单元测试的详细教程。 1. 准备工作 1.1 添加测试依赖 在 pom.xml 中添加测试相关依赖&#xff1a; <dependency><groupId>org.springframework.boot</…

React Hooks速成

1、useReducer 适用情况为对一个状态多种复杂操作,通俗的讲就是比如对count这个变量加减乘除的各种情况 改造前 import { useState } from "react";function App() {//计数器const [count, setCount] useState(0);const handleIncrement () > {setCount(coun…

k8s node 内存碎片化如何优化?

在 Kubernetes 集群中&#xff0c;内存碎片化&#xff08;Memory Fragmentation&#xff09;会导致系统无法分配连续的内存块&#xff0c;即使总内存充足&#xff0c;也可能触发 OOM&#xff08;Out of Memory&#xff09;或影响性能。以下是针对 k8s Node 内存碎片化的优化策略…

目标检测(Object Detection)研究方向常用数据集简单介绍

目录 一、目标检测研究方向简介 二、目标检测常用数据集详解 通用目标检测数据集 领域专用数据集 三、数据集选择建议 一、目标检测研究方向简介 目标检测是计算机视觉的核心任务之一&#xff0c;旨在从图像或视频中定位并识别出所有感兴趣的物体&#xff0c;输出其类别和…