WPF 命令绑定的各种方式
WPF 命令绑定的各种方式
引言
在WPF开发过程中,不得不学习的就是MVVM模式。但是在MVVM中又绕不开命令(Command)的使用。下面通过几种方式介绍我了解的WPF命令绑定方式。
如何使用
控件继承ICommand接口,直接使用Command
首先通过这里简单介绍Command在MVVM中的使用。
ViewModel类
// using System.ComponentModel;
// using System.Runtime.CompilerServices;
MainViewModel
/// <summary>/// Interactive logic for MainWindow/// </summary>public class MainViewModel : INotifyPropertyChanged{public MainViewModel(){SignInCommand = new RelayCommand(() =>{MessageBox.Show($"Hello {Username},welcome to Melphily's world");});}private string username;/// <summary>/// User name/// </summary>public string Username{get { return username; }set{username = value;RaisePropertyChanged();}}/// <summary>/// Sign in command/// </summary>public ICommand SignInCommand { get; private set; }#region Notify Handlerpublic event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };public void RaisePropertyChanged([CallerMemberName] string propertyName = null){PropertyChanged(this, new PropertyChangedEventArgs(propertyName));}#endregion}
Command类
// using System.Windows.Input;
RelayCommand
/// <summary>/// the command without input parameter/// </summary>public class RelayCommand : ICommand{public event EventHandler CanExecuteChanged = (sender, e) => { };private Action mAction;public RelayCommand(Action action){this.mAction = action;}public bool CanExecute(object parameter){// Always allow the action can execute.return true;}public void Execute(object parameter){// Take actionmAction.Invoke();}}
View类
MainWindow.xaml
<Window x:Class="Melphily.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:Melphily"mc:Ignorable="d"Title="Melphily" Height="450" Width="800"><Grid Background="Black"><Border VerticalAlignment="Center" Width="300" Padding="20 60" Background="White" CornerRadius="5"><Border.Effect><DropShadowEffect Color="#FF924AC3"/></Border.Effect><Border.BorderBrush><LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"><GradientStop Color="#FF22B5CD" Offset="1"/><GradientStop Color="#FFB92020"/></LinearGradientBrush></Border.BorderBrush><StackPanel ><TextBlock Text="Sign In" TextAlignment="Center" FontSize="22"><TextBlock.Foreground><LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"><GradientStop Color="#FF310F89" Offset="0"/><GradientStop Color="#FF26C6EA" Offset="1"/></LinearGradientBrush></TextBlock.Foreground></TextBlock><TextBlock Text="Username" Margin="0 20 0 0"/><TextBox Text="{Binding Username}" /><Button Command="{Binding SignInCommand}" Content="Sign In" Margin="0 20 0 0"/></StackPanel></Border></Grid>
</Window>
MainWindow.xaml.cs
/// <summary>/// Interactive logic for MainWindow.xaml/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();// Bind the Binding source to the DataContextDataContext = new MainViewModel();}}
至此,MVVM的简单应用就完成了。这里面简单实现了输入用户名登陆,在登陆(Sign In)操作时,使用了命令绑定的形式****,在ViewModel类(MainViewModel)接收命令,并做相应的处理。
运行效果:
扩展使用
上面通过较为完整的实例展示了MVVM模式中的Command绑定使用。但是一些WPF控件(例如ListBox)并不支持Command命令绑定。下面我们通过几种方式讨论如何解决,以ListBox举例。
使用InputBinding
Model
MusicItemModel.cs
public class MusicItemModel{public int Id { get; set; }public string Name { get; set; }public string Singer { get; set; }public MusicItemModel(){SelectedCommand = new RelayCommandWithParameter(p =>{MessageBox.Show($"Selected music is {Name} Singed by {Singer},the Id is {p}");});}/// <summary>/// Select command/// </summary>public ICommand SelectedCommand { get; private set; }}
Command
RelayCommandWithParameter.cs
/// <summary>/// the command without input parameter/// </summary>public class RelayCommandWithParameter : ICommand{public event EventHandler CanExecuteChanged = (sender, e) => { };private Action<object> mActionWithParameter;public RelayCommandWithParameter(Action<object> action){this.mActionWithParameter = action;}public bool CanExecute(object parameter){// Always allow the action can execute.return true;}public void Execute(object parameter){// Take actionmActionWithParameter.Invoke(parameter);}}
View Model
MusicListViewModel.cs
/// <summary>/// Interactive logic for MusicListPage/// </summary>public class MusicListViewModel : INotifyPropertyChanged{public MusicListViewModel(){Musics = new ObservableCollection<MusicItemModel>(){new MusicItemModel(){ Id=1, Name="甜甜的", Singer="周杰伦"},new MusicItemModel(){ Id=1, Name="说好的幸福呢", Singer="周杰伦"},new MusicItemModel(){ Id=1, Name="彩虹", Singer="周杰伦"},new MusicItemModel(){ Id=1, Name="一路向北", Singer="周杰伦"},new MusicItemModel(){ Id=1, Name="Married You", Singer="布鲁诺·马尔斯"},};}private ObservableCollection<MusicItemModel> musics;public ObservableCollection<MusicItemModel> Musics{get { return musics; }set { musics = value; RaisePropertyChanged(); }}#region Notify Handlerpublic event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };public void RaisePropertyChanged([CallerMemberName] string propertyName = null){PropertyChanged(this, new PropertyChangedEventArgs(propertyName));}#endregion}
View
MusicListPage.xaml.cs
/// <summary>/// Interactive logic for MusicListPage.xaml /// </summary>public partial class MusicListPage : Page{public MusicListPage(){InitializeComponent();DataContext = new MusicListViewModel();}}
MusicListPage.xaml
<Page x:Class="Melphily.MusicListPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Melphily"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"Title="MusicListPage"><Grid><ListBox ItemsSource="{Binding Musics}"><ListBox.ItemTemplate><DataTemplate ><Grid><Grid.InputBindings><MouseBinding MouseAction="LeftClick" Command="{Binding SelectedCommand}" CommandParameter="{Binding Id}"/></Grid.InputBindings><Grid.ColumnDefinitions><ColumnDefinition Width="300"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><TextBlock Grid.Column="0" Text="{Binding Name}"/><TextBlock Grid.Column="1" Text="{Binding Singer}"/></Grid></DataTemplate></ListBox.ItemTemplate></ListBox></Grid>
</Page>
命令绑定是使用Grid控件的InputBinding实现的。
<Grid.InputBindings><MouseBinding MouseAction="LeftClick" Command="{Binding SelectedCommand}" CommandParameter="{Binding Id}"/>
</Grid.InputBindings>
使用System.Windows.Interactivity.dll
呈现的内容和上面一样,只需要修改MusicListPage.xaml中的命令绑定即可。
System.Windows.Interactivity.dll这个时微软后期提供的。
1.将System.Windows.Interactivity.dll引入到项目中。
2.XAML中声明
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
3.XAML中使用
<i:Interaction.Triggers><i:EventTrigger EventName="MouseLeftButtonDown"><i:InvokeCommandAction Command="{Binding SelectedCommand}" CommandParameter="{Binding Id}"/></i:EventTrigger></i:Interaction.Triggers>
MusicListPage.xaml
<Page x:Class="Melphily.MusicListPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Melphily"xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"Title="MusicListPage"><Grid><ListBox ItemsSource="{Binding Musics}"><ListBox.ItemTemplate><DataTemplate ><Grid><!--<Grid.InputBindings><MouseBinding MouseAction="LeftClick" Command="{Binding SelectedCommand}" CommandParameter="{Binding Id}"/></Grid.InputBindings>--><i:Interaction.Triggers><i:EventTrigger EventName="MouseLeftButtonDown"><i:InvokeCommandAction Command="{Binding SelectedCommand}" CommandParameter="{Binding Id}"/></i:EventTrigger></i:Interaction.Triggers><Grid.ColumnDefinitions><ColumnDefinition Width="300"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><TextBlock Grid.Column="0" Text="{Binding Name}"/><TextBlock Grid.Column="1" Text="{Binding Singer}"/></Grid></DataTemplate></ListBox.ItemTemplate></ListBox></Grid>
</Page>
自定义模板使用含有ICommand接口的控件传递命令
对于没有继承ICommand接口的控件,可以重定义控件的模板,并在模板中加入可以使用Command绑定的控件例如Button来实现命令的绑定。
使用上面的示例,只修改数据模板,如下所示。
MusicListPage.xaml
<Page x:Class="Melphily.MusicListPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Melphily"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"Title="MusicListPage"><Grid><ListBox ItemsSource="{Binding Musics}"><ListBox.ItemTemplate><DataTemplate ><Grid><Grid.ColumnDefinitions><ColumnDefinition Width="300"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><TextBlock Grid.Column="0" Text="{Binding Name}"/><TextBlock Grid.Column="1" Text="{Binding Singer}"/><!-- 可以绑定命令的控件 --><Button Grid.ColumnSpan="2" Command="{Binding SelectedCommand}" CommandParameter="{Binding Id}"Foreground="Transparent" Background="Transparent" /></Grid></DataTemplate></ListBox.ItemTemplate></ListBox></Grid>
</Page>
虽然这种方式比较简单粗暴,但由于是直接在模板上面操作,所有控件是否有焦点变得非常重要了,还有就是需要隐藏控件的一些不需要显示的样式。
样式没设置好,会出现意想不到的情况。如下:
自定义模板使用用户控件(UserControl)【添加Command依赖属性】传递命令
鉴于上面自定义模板使用含有ICommand接口的控件传递命令
的方式存在的一些弊端,我们可以自定义带有命令的控件来解决不便利的地方。
1.自定义CommandControl控件
CommandControl.xaml
<UserControl x:Class="Melphily.UiCore.CommandControl"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Melphily.UiCore"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"Background="Transparent">
</UserControl>
CommandControl.xaml.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;namespace Melphily.UiCore
{/// <summary>/// CommandControl.xaml 的交互逻辑/// </summary>public partial class CommandControl : UserControl{public CommandControl(){InitializeComponent();MouseLeftButtonDown += OnMouseLeftButtonDown;}private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs){if (Command != null){if (Command.CanExecute(CommandParameter)){Command.Execute(CommandParameter);}}}public static readonly DependencyProperty CommandProperty =DependencyProperty.Register("Command", typeof(ICommand),typeof(CommandControl),new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None));public ICommand Command{get { return (ICommand)GetValue(CommandProperty); }set { SetValue(CommandProperty, value); }}public static readonly DependencyProperty CommandParameterProperty =DependencyProperty.Register("CommandParameter", typeof(object),typeof(CommandControl),new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None));public object CommandParameter{get { return (object)GetValue(CommandParameterProperty); }set { SetValue(CommandParameterProperty, value); }}}
}
2.在模板中使用CommandControl
MusicListPage.xaml
<Page x:Class="Melphily.MusicListPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Melphily"xmlns:uicore="clr-namespace:Melphily.UiCore"xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"Title="MusicListPage"><Grid><ListBox ItemsSource="{Binding Musics}"><ListBox.ItemTemplate><DataTemplate ><uicore:CommandControl Command="{Binding SelectedCommand}"CommandParameter="{Binding Id}"><Grid><Grid.ColumnDefinitions><ColumnDefinition Width="300"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><TextBlock Grid.Column="0" Text="{Binding Name}"/><TextBlock Grid.Column="1" Text="{Binding Singer}"/></Grid></uicore:CommandControl></DataTemplate></ListBox.ItemTemplate></ListBox></Grid>
</Page>
由于CommandControl是一个透明的控件,因此不用考虑样式的问题,可以直接使用。其次它是内容控件,因此该控件是始终存在焦点。
但是,如果将该控件作为模板(ControlTemplate/DataTemplate)时,发现无法对容器内的控件设置名称,因此,在设置样式模板时局限性会很大。
自定义模板使用自定义控件(CustomControl)【添加Command依赖属性】传递命令
鉴于用户控件带来的弊端,我们依然可以使用自定义控件(CustomControl)来解决。
创建一个自定义控件:
在项目中点击添加–》新建项
然后找到“CustomControl”或者“WPF自定义控件”,设置好名称,点击创建。
创建之后首先会存在一个对应.cs文件,然后会自动创建一个Theme(主题)文件夹,并创建一个Generic.xaml文件(通用样式文件)。
接下来我们编写自定义控件
1.加入我们的命令依赖属性和相关处理事件。
CommandControl.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;namespace Deamon.UiCore
{/// <summary>/// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。////// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。/// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根/// 元素中:////// xmlns:MyNamespace="clr-namespace:Deamon.UiCore"///////// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。/// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根/// 元素中:////// xmlns:MyNamespace="clr-namespace:Deamon.UiCore;assembly=Deamon.UiCore"////// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,/// 并重新生成以避免编译错误:////// 在解决方案资源管理器中右击目标项目,然后依次单击/// “添加引用”->“项目”->[浏览查找并选择此项目]///////// 步骤 2)/// 继续操作并在 XAML 文件中使用控件。////// <MyNamespace:CommandControl/>////// </summary>public class CommandControl : ContentControl{static CommandControl(){DefaultStyleKeyProperty.OverrideMetadata(typeof(CommandControl), new FrameworkPropertyMetadata(typeof(CommandControl)));}public CommandControl(){MouseLeftButtonDown += CommandControlCC_MouseLeftButtonDown;}private void CommandControlCC_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){if (Command != null){if (Command.CanExecute(CommandParameter)){Command.Execute(CommandParameter);}}}private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs){if (Command != null){if (Command.CanExecute(CommandParameter)){Command.Execute(CommandParameter);}}}public static readonly DependencyProperty CommandProperty =DependencyProperty.Register("Command", typeof(ICommand),typeof(CommandControl),new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None));public ICommand Command{get { return (ICommand)GetValue(CommandProperty); }set { SetValue(CommandProperty, value); }}public static readonly DependencyProperty CommandParameterProperty =DependencyProperty.Register("CommandParameter", typeof(object),typeof(CommandControl),new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None));public object CommandParameter{get { return (object)GetValue(CommandParameterProperty); }set { SetValue(CommandParameterProperty, value); }}}
}
注释是默认加上的,是用来引导你如何设计和使用该自定义控件。默认情况下,自定义控件是继承自Control类的,因为我们的命令控件是需要包裹其它控件,所以直接继承ContentControl会减少我们对内容设计的逻辑代码。(PS:如果不这么做也可以自己添加Content属性,然后再面板中使用ContentPresenter将Content显示到界面上。)
2.在Generic.xaml文件中修改控件默认样式
Generic.xaml
<ResourceDictionaryxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:Deamon"xmlns:uicore="clr-namespace:Deamon.UiCore"><!-- 带命令绑定的内容控件 --><Style TargetType="{x:Type uicore:CommandControl}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type uicore:CommandControl}"><ContentControl><ContentPresenter/></ContentControl></ControlTemplate></Setter.Value></Setter></Style>
</ResourceDictionary>
ContentPresenter默认情况下已经将Content属性绑定到了改控件上,如果是其它控件,需要具体了解(绑定、样式、模板等)相关知识。
3.在模板中使用CommandControl
MusicListPage.xaml
<Page x:Class="Melphily.MusicListPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Melphily"xmlns:uicore="clr-namespace:Melphily.UiCore"xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"Title="MusicListPage"><Grid><ListBox ItemsSource="{Binding Musics}"><ListBox.ItemTemplate><DataTemplate ><uicore:CommandControl Command="{Binding SelectedCommand}"CommandParameter="{Binding Id}"><Grid><Grid.ColumnDefinitions><ColumnDefinition Width="300"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><TextBlock Grid.Column="0" Text="{Binding Name}"/><TextBlock Grid.Column="1" Text="{Binding Singer}"/></Grid></uicore:CommandControl></DataTemplate></ListBox.ItemTemplate></ListBox></Grid>
</Page>
使用方式和UserControl一模一样,只是控件的定义方式不一样而已。
WPF 命令绑定的各种方式相关推荐
- WPF中的命令与命令绑定(二)
WPF中的命令与命令绑定(二) 周银辉 在WPF中,命令(Commanding)被分割成了四个部分,分别是IC ...
- WPF(三) WPF 命令
1.WPF 命令的概念 WPF 区别于 WinForm,在继承WinForm熟悉的事件和委托技术之上,还提供了一套完善的命令(Command)系统.简单来说,命令是一个任务的完整封装,例如保存,复 ...
- MVVM 下 ContextMenu的命令绑定
原文:MVVM 下 ContextMenu的命令绑定 由于ContextMenu不继承父级的DataContext,所以如果要绑定父级的DataContext,直接DataContext=" ...
- 【WPF】WPF 命令
命令将操作的语义和发起方与其逻辑分开. 这使得多个完全不同的源可以调用相同的命令逻辑,并使得可以针对不同的目标对命令逻辑进行自定义. 命令的语义在所有的应用程序和类中是一致的,但是操作的逻辑是所作用于 ...
- WPF Binding(绑定)详解
Binding概念理解: WPF为了实现了UI与数据逻辑的解耦,将UI从数据逻辑中分离出来形成Xaml文件,而UI与数据逻辑之间的联系则通过Bingding来实现.Bingding就像UI与数据逻辑之 ...
- 另一个绑定事件的方式 为元素绑定事件的区别
另一个绑定事件的方式 <!DOCTYPE html> <html lang="en"> <head><meta charset=" ...
- wpfのuri(让你完全明白wpf的图片加载方式以及URI写法)
原文:wpfのuri(让你完全明白wpf的图片加载方式以及URI写法) 绝对 pack WPF URI pack://application:,,,/是协议:",,,"是" ...
- C#使用Xamarin开发可移植移动应用(4.进阶篇MVVM双向绑定和命令绑定)附源码
今天的学习内容? 今天我们讲讲Xamarin中的MVVM双向绑定,嗯..需要有一定的MVVM基础.,具体什么是MVVM - -,请百度,我就不多讲了 效果如下: 正文 1.简单的入门Demo 这个时间 ...
- js执行shell命令的几种方式(Node)
js执行shell命令的几种方式(Node) nodejs 执行cmd或shell命令 Nodejs调用shell脚本 nodejs调用shell
最新文章
- 95后女程序员一下班就溜,拒绝加班!下班玩消失,不回信息!leader吐槽:95后都这么有个性吗?...
- 【做题】TCSRM601 Div1 500 WinterAndSnowmen——按位考虑dp
- Mysql 死锁过程及案例详解之显式与隐式锁Explicit Table Lock Implicit Table Lock
- 以CSGO为例 分析不同网络延时下FPS游戏同步的实现
- .NET微服务最佳实践eShopOnContainers
- Activiti配置实例以及Spring集成配置
- java中的内存一般分成几部分?
- 先排序,再限定记录数,然后计算指定字段的总和
- native与ascii互转
- 东航期货行情接口和交易接口(20190509)
- Android无界面编程之使用Service
- mysql必知必会心得_SQL必知必会知识总结
- Firebird学习(02):数据库的中文参考资料
- 最新雷速问卷调查系统V7.15+ASP内核开发
- Android 6种加载网络图片的第三方详解
- H5 六边形消除游戏开发 1
- 内农大《嵌入式基础》实验一 Shell编程
- 深入理解计算机系统_00
- github优秀项目源码汇总---Android
- 给hacke拨乱反正 黑客、红客、蓝客究竟是什么--来自:互联网实验室
热门文章
- 续集关于上次简单微信小程序制作 (快递100查询)
- 【网络】从日常开发说起,浅谈HTTP协议是做什么的
- 真假5G之争到了终结的时候,中国移动或将以低频5G击败5G厘米波
- 修改jupyter notebook中的字体
- 《python语言程序设计基础》—— 第7章
- Flutter 学习路线图
- 【考研数据】三.2022年BJTU计算机学院考研录取数据分析
- 关于uni-app导航栏中 中间大图标的设置
- 家用投影仪什么牌子好又便宜?
- 论文笔记 |【CVPR2021】Uformer: A General U-Shaped Transformer for Image Restoration