基础说明

DataGrid是WPF提供的基础控件,它可以非常轻松的呈现出一张表格,本文章会按照从易到难的顺序依次将DataGrid的使用方法进行解说,除了MSDN上给出的最基本的例子之外,给出了三个比较常见的在真实使用场景下使用的例子,这三个例子已经基本覆盖了我们能够遇到的大部分使用场景了。

基础实例:MSDN上,使用DataGrid绑定一个数据模型

在MSDN上,可以非常轻松的找到有关于对DataGrid控件进行数据绑定的方法,微软提供的绑定方法是这样的:
MSDN源地址点击这里查看

执行步骤:

1、有一个已经定义好的类型:

public class Customer
{public string FirstName { get; set; }public string LastName { get; set; }public Uri Email { get; set; }public bool IsMember { get; set; }
}

2、编写一个XAML的DataGrid控件

在这里,DataGrid关联数据比较灵活,就不一一列举了,下边贴出的代码只使用了其中一种关联方式:

  1. 可以像例子里一样:先将ItemsSource使用Binding空出path属性,然后使用DataContext指定数据源
  2. 也可以在前端不指定ItemsSource,然后直接在C#代码中指定ItemsSource:this.CustomerDataGrid.ItemsSource = list;
  3. 也可以直接在XAML前端直接指定容器
<DataGrid Name="DG1" ItemsSource="{Binding}" AutoGenerateColumns="False" ><DataGrid.Columns><DataGridTextColumn Header="Column1"  Binding="{Binding FirstName}"/><DataGridTextColumn Header="Column2" Binding="{Binding LastName}" /><DataGridHyperlinkColumn Header="Column3" Binding="{Binding Email}"  /><DataGridCheckBoxColumn Header="Column4" Binding="{Binding IsMember}" /></DataGrid.Columns>
</DataGrid>

3、通过DataContext关联容器和DataGrid控件实例

ObservableCollection<Customer> list = InitCustomerData.InitData();  // 向容器中添加数据
this.CustomerDataGrid.DataContext = list;

最终,通过DataContext将类型实例的容器与DataGrid的实例进行关联,效果如下,就可以在DataGrid当中显示出来(我这个截图稍微有点出入,多了个我做实验的Column5):

但是,这个用法有以下几个缺点

  1. DataGrid内部只有DataGrid预设的几种数据类型,没有办法扩展
  2. 只有显示功能,没有对DataGrid中的数据有任何操作
  3. DataGrid数据结构在前端被写死,如果存在很多张表的话,就需要对应数量的前端代码

注:以上代码的实例可以在WPF项目下的主界面逻辑处理InitaListToDataGridColumn函数当中实现(源代码地址在文章最后给出)

实际应用

应用实例1:通过数据模板扩展表格单元格的显示内容

在应用实例1当中,解决了基础实例当中的两个问题:

  1. DataGrid可以填充任意的数据
  2. DataGrid可以通过模板添加按钮等带有事件的控件来控制单元格

实现的方法是使用“数据模板(DataTemplate)”来填充DataGrid的单元格,这个数据模型可以是多种多样的,比如:

  1. Image控件显示图片
  2. 一个TextBlock加button按钮的组合
  3. 等等~~~

执行步骤:

1、前端使用DataTemplate定义一个单元格要显示的控件内容

在这里,可以看到DataGrid控件当中的前两列,编号和时间戳仍然是基础的使用方法,而第三列的消息内容,则需要有更多的功能,比如一个点击事件,这个点击事件可以查看消息更详细的内容,所以我为这个单元格设计了一个TextBlock控件显示消息的简略内容,以及一个按钮,这个按钮点击后,可以显示这个消息的详细内容

这个数据模板需要使用x:Type关联一个类型作为它的模型,Text显示内容可以是这个类型的其中一个属性,而按钮的点击事件则可以直接调用这个类型的成员函数或回调函数

<!-- 一个数据模板,使用在后边DataGrid的最后一个单元格 -->
<Border.Resources><!-- 这个数据模板使用MessageModel这个类型作为数据模型 --><DataTemplate x:Key="cellEditingTemplate" DataType="{x:Type model:MessageModel}"><Grid><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition Width="15"/></Grid.ColumnDefinitions><!-- 控件类型是一个TextBlock和一个Button控件的组合 --><TextBlock Grid.Column="0" Text="{Binding m_content}"/><Button Grid.Column="1" Content="..." Command="{Binding ShowCommand}"/></Grid></DataTemplate><DataTemplate x:Key="cellDropBox" DataType="{x:Type model:MessageModel}"><ComboBox ItemsSource="{Binding m_content_detail}" SelectedIndex="0" /></DataTemplate>
</Border.Resources><!-- 表格,用来显示MessageVM中所有的消息,使用ItemsSource指定数据源 -->
<DataGrid AutoGenerateColumns="False" x:Name="MsgDataGrid" ItemsSource="{Binding Path=.}" BeginningEdit="MsgDataGrid_BeginningEdit" ><DataGrid.Columns><DataGridTextColumn Header="编号" Binding="{Binding m_No}"/><DataGridTextColumn Header="时间戳" Binding="{Binding m_time}"/><!-- 自定义的数据模板添加到单元格的最后 --><DataGridTemplateColumn Header="消息内容" CellTemplate="{StaticResource ResourceKey = cellEditingTemplate}" CellEditingTemplate="{StaticResource ResourceKey = cellEditingTemplate}"/><DataGridTemplateColumn Header="消息详情" CellTemplate="{StaticResource ResourceKey=cellDropBox}"/></DataGrid.Columns>
</DataGrid>

2、定义一个与DataTemlate相关联的类型

在前端WPF代码中,DataTemplate当中,指定了类型MessageModel为这个模板的模型,并且,模板当中的第一个TextBlock使用了类型中的属性m_content,第二个Button按钮使用了ICommand回调函数,同时,这个MessageModel还是DataGrid另外两列的数据模板

public class MessageModel
{/// <summary>/// 可触发的命令:显示消息内容;/// </summary>private ICommand mShowCommand;public ICommand ShowCommand{get{if (mShowCommand == null){mShowCommand = new RelayCommand(() =>{ExecuteAction();},() => CanExecuteFunc());}return mShowCommand;}}private bool CanExecuteFunc(){return true;}private void ExecuteAction(){Console.WriteLine("Content is" + this.m_content);foreach(var iter in this.m_content_detail){Console.WriteLine("Content Detail is " + iter);}}/// <summary>/// 消息编号;/// </summary>private string No;public string m_No{get { return No; }set { No = value; }}/// <summary>/// 时间戳;/// </summary>private DateTime time;public DateTime m_time{get { return time; }set { time = value; }}/// <summary>/// 消息内容A;/// </summary>private string content;public string m_content{get { return content; }set { content = value; }}private List<string> content_detail;public List<string> m_content_detail{get { return content_detail; }set { m_content_detail = value; }}/// <summary>/// 消息的源IP地址;/// </summary>private string source;public string m_source{get { return source; }set { source = value; }}/// <summary>/// 消息的目的IP地址;/// </summary>private string dest;public string m_dest{get { return dest; }set { dest = value; }}
}public class RelayCommand : ICommand
{private Action mExecuteAction;              // 执行命令;private Func<bool> mCanExecuteFunc;         // 命令是否可以执行;public RelayCommand(Action executeAction, Func<bool> canExecuteFunc){mExecuteAction = executeAction;mCanExecuteFunc = canExecuteFunc;}public bool CanExecute(object parameter){return mCanExecuteFunc.Invoke();}public void Execute(object parameter){mExecuteAction.Invoke();}public event EventHandler CanExecuteChanged;}

3、定义一个与DataGrid控件直接交互的VM层,用来控制控件的显示内容

这种设计思路是MVVM框架的思路,可以比较好的解耦前端WPF层(View层)与后端数据模型(Model层),在VM层(ViewModel),专门用一个List或者ObservableCollection容器保存想要在前端DataGrid中显示的容器列表

public class MessageVM
{// 存放所有消息内容的地方;private volatile ObservableCollection<MessageModel> m_messagelist;public ObservableCollection<MessageModel> messagelist{get{return m_messagelist;}set{m_messagelist = value;}}public MessageVM(){messagelist = new ObservableCollection<MessageModel>();}
}

4、在主程序当中,将VM层与对应的DataGrid控件进行DataContext关联

这个就是处理逻辑了,没什么好说的,用这个处理逻辑为VM层添加一些实验数据,以便显示在前端的DataGrid当中

public MessageVM m_MessageVM =  new MessageVM();             // MessageVM层,用来显示MessageModel的;
this.MsgDataGrid.DataContext = m_MessageVM.messagelist;// 使用一个线程更新DataGrid控件
Task a = new Task(()=>
{int temp = 0;while(true){temp = temp + 1;Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate{m_MessageVM.messagelist.Add(new MessageModel(){m_No = temp.ToString(),m_time = DateTime.Now,m_content = "content",m_source = "172.27.0.1",m_dest = "172.27.0.2"});});Thread.Sleep(1233);}
});a.Start();

最终,呈现的效果如下,在点击消息内容单元格内的"…"按钮后,既可以触发查看内容的详细信息

这个方法的主要核心点就在于使用了DataTemplate数据模板,这个数据模板可以很好的帮助你在DataGrid表的单元格内放置任意你想要的形态,但这样做也会带来一些问题

  1. 如果只是简单的编辑表格,或者对表格本身进行操作,DataTemplate就无能为力了:

    1. 比如编辑单元格
    2. 比如鼠标滑过表格或单元格时,有悬浮窗提示信息
    3. 等等这样针对表格,某个单元格本身,而不是针对某个单元格中的内容操作
  2. 这个表格仍然没有解决前端代码被写死,Model和View必须一一对应的问题

应用实例2:使用DataGrid自带的事件对表格进行操作

以上那种形式,是通过自定义单元格来解决大部分对表格操作的需求,但是,如同上例,简单操作单元格的话,用鼠标或者控件本身事件就好了,在每个单元格内都增加一个按钮也比较难看,况且自定义DataTemplate针对整张表格的操作也时无法实现。所以大部分的基本的操作,利用DataGrid本身自带的事件实现就好了

执行步骤:

1、在前端定义一个表格

这里注意一点:将SelectionUnit=“Cell” SelectionMode="Single"这两个属性设定后,就可以对某个单元格进行操作了,默认情况下,点击DataGrid后,默认是选中整行的

<!-- 对DataGrid进行更加丰富的操作,比如单元格编辑事件等等 -->
<Border BorderBrush="Black" BorderThickness="1" Grid.Row="3" Margin="5,5,5,5"><DataGrid x:Name="CustomerDataGrid_AddEvent" ItemsSource="{Binding Path = .}" AutoGenerateColumns="False" SelectionUnit="Cell" SelectionMode="Single"><DataGrid.Columns><DataGridTextColumn Header="Column1"  Binding="{Binding column1.name}"/><DataGridHyperlinkColumn Header="Column2" Binding="{Binding column2.name}"  /><DataGridCheckBoxColumn Header="Column3" Binding="{Binding column3.name}" /></DataGrid.Columns></DataGrid>
</Border>

2、 为这张表格的单元格定义一个数据类型

为了能够让单元格中具有更多的操作行为,我为这个单元格单独定义了类型,在C#后台填充单元格的时候,直接填充类型即可,然后在WPF前端,就可以访问这个类型对应的某个属性显示在DataGrid控件当中了,就如同第一步{Binding column2.name}这样,实则它访问的就是GridCell类型的name

public class GridCell
{public string name { get; set; }public void EditingCalback(){Console.WriteLine("GridCell Editing Callback:" + name);}
}

3、为这张表格定义一个VM数据层

这个VM数据层就是为了保存这张表所有要呈现的数据,及其操作表格时对应的函数逻辑

public class DataGridWithEvent
{public GridCell column1 { get; set; }       // 向单元格填写自定义个类型;public GridCell column2 { get; set; }       // 向单元格填写自定义个类型;public GridCell column3 { get; set; }       // 向单元格填写自定义个类型;// 当表格控件被编辑时,会调用单元格自身实例对应的函数;public void JudegePropertyCall_CellEditing(string colHeader){switch(colHeader){case "Column1":this.column1.EditingCalback();break;case "Column2":this.column2.EditingCalback();break;case "Column3":this.column3.EditingCalback();break;default:break;}}}

4、最后在逻辑处理代码中填充数据和对应的事件

ObservableCollection<DataGridWithEvent> list = InitDataGridWithEventData.InitData();
this.CustomerDataGrid_AddEvent.DataContext = list;// 以下是表格事件;
this.CustomerDataGrid_AddEvent.BeginningEdit += CustomerDataGrid_AddEvent_BeginningEdit;              // 事件一:单元格开始编辑事件;
this.CustomerDataGrid_AddEvent.SelectionChanged += CustomerDataGrid_AddEvent_SelectionChanged;        // 事件二:单元格选择出现变化时;
this.CustomerDataGrid_AddEvent.GotFocus += CustomerDataGrid_AddEvent_GotFocus;                        // 事件三:DataGrid表格点击单元格获取焦点时;// 以下是鼠标事件;
this.CustomerDataGrid_AddEvent.MouseMove += CustomerDataGrid_AddEvent_MouseMove;                      // 事件四:鼠标移动到某个单元格上时触发(实验函数增加了鼠标拖动效果);
this.CustomerDataGrid_AddEvent.GotMouseCapture += CustomerDataGrid_AddEvent_GotMouseCapture;          // 事件五:使用这个事件事件鼠标拖拽更加稳定;this.CustomerDataGrid_AddEvent.MouseLeftButtonDown += CustomerDataGrid_AddEvent_MouseLeftButtonDown;  // 事件六:鼠标左键点击事件,这个事件只针对DataGrid整个表格;
this.CustomerDataGrid_AddEvent.MouseEnter += CustomerDataGrid_AddEvent_MouseEnter;                    // 事件七:鼠标进入整个表格时触发,且只触发一次;// 另一个元素接收鼠标拖拽事件;
this.ReceiveDataLabel.AllowDrop = true;
this.ReceiveDataLabel.Drop += ReceiveDataLabel_Drop;

列出比较常用的事件:

由于MSDN上边,有关于事件列表中的描述都比较晦涩难懂,所以在此列出一些比较常见的

表格操作系列事件(未完待续)

鼠标操作系列事件

  1. MouseMove

    1. 当鼠标进入到DataGrid控件真实填充过的单元格后,鼠标每移动到某个元素的时候,都会触发这个事件
    2. 带有两个入参,几个比较重要的可以获取的参数:
      1. object sender:DataGrid本身
      2. MouseEventArgs e:e.OriginalSource is DataGridCell
      3. 获取表格当中的元素类型:(e.OriginalSource as DataGridCell).DataContext
  2. GotMouseCapture
    1. 当鼠标进入到DataGrid控件真实填充过的单元格后,鼠标每点击某个单元格的时候,就会触发这个事件
    2. 带有两个入参,几个比较重要的可以获取的参数:
      1. object sender:DataGrid本身
      2. e.OriginalSource is DataGrid
      3. 获取表格当中的元素类型:foreach (var iter in (e.OriginalSource as DataGrid).SelectedCells)

以上两个鼠标事件的作用区域见下图:即有真实填充数据的区域

应用场景1:
MouseMove和GotMouseCapture可以用来实现鼠标拖拽事件

使用DragDrop.DoDragDrop就可以实现鼠标拖拽的起点,使用[控件名称].Drop += [funcCallback]实现接收鼠标拖拽的事件。具体可参见GitHub中的源码

  1. MouseEnter

    1. 当鼠标进入到整个DataGrid表格的时候,会触发一次,且不会重复触发,直到鼠标离开DataGrid控件后,再次进入之后,才会再次触发
    2. 带有两个入参,三个可以获取的比较重要的参数:
      1. sender:DataGrid本身
      2. e.Source is DataGrid本身
      3. e.OriginalSource is DataGrid本身

MouseEnter鼠标事件的作用区域为DataGrid整表,见下图:

  1. MouseLeftButtonDown

    1. 当鼠标在DataGrid没有填充数据的单元格处,发生了鼠标左键按下的时候触发的事件
    2. 带有两个参数,两个可以获取的比较重要的参数:
      1. sender is DataGrid本身
      2. e.Source is DataGrid本身

MouseLeftButtonDown鼠标事件的作用区域为DataGrid没有填充单元格的区域,见下图:

应用实例3:通过动态类型实现一个动态DataGrid表格(即可以填充任何数据类型)

以上两种实例的做法的核心思想是:每一个DataGrid都对应一个数据模型,这样做的好处就是操作数据模型就相当于操作DataGrid表格了,但是这样做有一个缺陷,如果数据模型增加到一定的数量,比如几千个,这样你就需要在前台声明几千个表格,后台代码也需要有对应几千个数据模型,再进一步,表格的内容如果无法确定是动态加载的,这样的方法就不具备任何可行性了

解决问题的思路:

实现这个的思路其实非常淳朴简单,使用dynamic动态类型,在运行时动态的加载表格的ViewModel层。这样一来,我们就可以在运行时为某一个DataGrid动态的生成与其对应的类型了。具体Dynamic类型在此就不展开说了,可参见MSDN

执行步骤:

1、声明一个动态类型的VM层

这个VM层中保存了所有生成一个类型的数据,包括:

  • Properties:属性名称和属性类型的对应关系

    • key:类型中属性的名字
    • value:类型中属性的类型的实例
  • colName_Property:列名和属性名的对应关系
    • key:DataGrid表的列名称
    • value:Property的属性名称
  • AddProperty:动态方法,用于动态给Properties和ColName_Property添加对应关系
public class DyDataDridModel : DynamicObject
{// 用来保存这个动态类型的所有属性;// string为属性的名字;// object为属性的值(同时也包含了类型);Dictionary<string, object> Properties = new Dictionary<string, object>();// 用来保存中文列名与属性的对应关系;Dictionary<string, string> ColName_Property = new Dictionary<string, string>();// 为动态类型动态添加成员;public override bool TrySetMember(SetMemberBinder binder, object value){if (!Properties.Keys.Contains(binder.Name)){Properties.Add(binder.Name, value);}return true;}// 为动态类型动态添加方法;public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result){// 可以通过调用方法的手段添加属性;if (binder.Name == "AddProperty" && binder.CallInfo.ArgumentCount == 3){string name = args[0] as string;if (name == null){//throw new ArgumentException("name");  result = null;return false;}// 向属性列表添加属性及其值;object value = args[1];Properties.Add(name, value);// 添加列名与属性列表的映射关系;string column_name = args[2] as string;ColName_Property.Add(column_name, name);result = value;return true;}if(binder.Name == "JudgePropertyName_StartEditing" && binder.CallInfo.ArgumentCount == 1){string columnname = args[0] as string;if(columnname == null){result = null;return false;}// 在当前列名于属性列表中查找,看是否有匹配项;if(ColName_Property.ContainsKey(columnname)){string key = ColName_Property[columnname];if(Properties.ContainsKey(key)){object property = Properties[key];}}else{}}return base.TryInvokeMember(binder, args, out result);}// 获取属性;public override bool TryGetMember(GetMemberBinder binder, out object result){return Properties.TryGetValue(binder.Name, out result);}}

2、在前端声明一个没有任何列定义的DataGrid表格:

<DataGrid AutoGenerateColumns="False" x:Name="MsgDataGrid_AutoGenCol"/>

3、在控制类中,可以使用DyDataDridModel动态添加一个类及其属性
动态为DyDataDridModel添加多个属性以及对应的值,这些属性就相当于表格中的列,值就相当于每行对应的数据,下边的例子就增加了一行数据(Grid上文中已经列出过了,这里使用同样的Gridcell)

// 支持动态添加内容的类型
dynamic model = new DyDataDridModel();// 向单元格内添加内容,这里是添加了一整行内容;
model.AddProperty("property2", new GridCell() { name = "343" }, "列2");
model.AddProperty("property0", new GridCell() { name = "123" }, "列0");
model.AddProperty("property1", new GridCell() { name = "321" }, "列1");
list.Add(model);// 定义每一列显示的内容以及Binding的对象
for (int i = 0; i <= 2; i++)
{DataGridTextColumn column = new DataGridTextColumn();column.Header = "列" + i;column.Binding = new Binding("property" + i + ".name");this.MsgDataGrid_AutoGenCol.Columns.Add(column);
}
this.MsgDataGrid_AutoGenCol.ItemsSource = list;

把上边的语句代码翻译回方式一或方式二的模式,是这个样子的:

// VM层模型
class VModel
{public GridCell property2;public GridCell property0;public GridCell property1;
}// 数据模型
public class GridCell
{public string name { get; set; }public void EditingCalback(){}
}<!--view层-->
<DataGrid x:Name="CustomerDataGrid" ItemsSource="{Binding Path = .}" AutoGenerateColumns="False"  ><DataGrid.Columns><DataGridTextColumn Header="列2"  Binding="{Binding property2.name}"/><DataGridTextColumn Header="列0" Binding="{Binding property0.name}" /><DataGridHyperlinkColumn Header="列1" Binding="{Binding property1.name}"  /></DataGrid.Columns>
</DataGrid>// 逻辑层:
ObservableCollection<VModel> list = new ObservableCollection<VModel>();
list.add(new GridCell(){ property2.name = "343",property0.name = "123",property1.name = "321"
});
CustomerDataGrid.Datacontext = list;

动态加载表的最终效果如下:


以上,就是目前所有我对WPF的DataGrid控件使用的归纳,总结下来,需要掌握的知识点并不难。如果想要对DataGrid进行灵活应用的话,需要对MVVM架构有一个大致的认识,并且对动态类型有一定的了解,熟悉Python的同学,对动态类型认识起来,肯定就轻松很多了。

另外,以上三种实现方式,都可以在我的一个项目中找到:

https://github.com/visiontrail/CSharpKnowledge

本文有关DataGrid的内容都在WPF项目当中

有关WPF中DataGrid控件的基础应用总结相关推荐

  1. WPF中DataGrid控件

    WPF中DataGrid控件的个别属性使用 //设置不可自动拉伸宽度dataGrid.CanUserResizeColumns = false;//第一列不可见dataGrid.HeadersVisi ...

  2. WPF 中DataGrid控件显示和设置数据

    一.基础知识 1.DataGrid控件:用来显示数据的控件,从对象集合中获取信息并在具有行和单元格的网格中显示信息.每行和单独的对象相对应,并且每列和对象的某个属性相对应. 2.在DataGrid 中 ...

  3. 详解WPF 4 DataGrid控件的基本功能

    分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 详解WPF 4 D ...

  4. WPF之DataGrid控件使用

    WPF之DataGrid控件使用 一.DataGrid简介 二.DataGrid数据源绑定 三.DataGrid单元格编辑触发事件 四.DataGrid增加删除行 五.DataGrid数据触发器 参考 ...

  5. WPF 自定义DataGrid控件样式

    WPF 自定义DataGrid控件样式 样式一: 样式代码: <!--DataGrid样式--><Style TargetType="DataGrid">& ...

  6. WPF中一个控件绑定另一个控件的属性

    原文:WPF中一个控件绑定另一个控件的属性 如同一个Grid中的一个按钮根据另一个按钮的显示与否作出不同的响应: 绑定的时候通过ElementName来指定控件 <Grid Margin=&qu ...

  7. wpf中使用控件时,最好给控件取一个好的名字

    wpf中使用控件时,最好给控件取一个好的名字, 比如按钮A可以  取名为 btnA 这样使用会是编程清晰.

  8. VB.net数据库编程中DataGrid控件的使用技巧

    VB.net数据库编程中DataGrid控件的使用技巧 如何用同一个DataGrid显示不同的数据表:如何用DataGrid显示主表/明细表的内容:如何用DataGrid分页显示或编辑数据表的记录.这 ...

  9. WPF中通过控件Margin属性设置控件位置

    WPF中通过控件Margin属性设置控件位置 一.Margin属性简介 二.Margin在cs文件中定义 三.Margin设置控件位置 四.参考文档 一.Margin属性简介 在使用WPF进行页面设计 ...

最新文章

  1. 【杂】LaTeX中一些符号的输入方法
  2. 一文读懂图像局部特征点检测算法
  3. python列表不包含哪个内置函数_python 列表的推导器和内置函数
  4. python实现排序算法_python实现·十大排序算法之插入排序(Insertion Sort)
  5. Application log save debug - how log data is persisted to database table
  6. Java中的方法(形参及实参)return返回类型
  7. Task类的简单介绍
  8. 解决OpenCV编译时./bin: error while loading shared libraries: libopencv_highgui.so.3.2: cannot open的问题
  9. 拓端tecdat|R语言使用特征工程泰坦尼克号数据分析应用案例
  10. ASCII码值转化十六进制,十进制数;十六进制字符值转十进制,ASCII码值;
  11. 吴恩达深度学习笔记 最全最详细!这一篇足够了!
  12. ADC SFDR无杂散动态范围
  13. Zune WIFI无线同步教程
  14. coherence-based label propagation over time series for accelerated active learning
  15. 【OpenCV】计算两幅图片视觉差
  16. 【算法】什么是OJ系统?
  17. PostMan中文插件支持8.12.2
  18. 计算机word怎么录制宏,Word 2013中录制宏的方法
  19. 计算机自动维护有用吗,Win10怎么开启自动维护功能?系统自动维护有什么作用?...
  20. HNOI 2018 滚粗记

热门文章

  1. 2021年中国智慧仓储研究报告 附下载
  2. Vivo手机的权限管理
  3. ACM第10题:珠子问题
  4. matlab pca可视化,[转]PCA的介绍,实例及绘图
  5. 网络流量的6个主要来源
  6. 关于深度学习应用于场景合成/自动布局的相关的论文阅读【211227更新】
  7. IntelliJ IDEA 修改滚动条颜色
  8. 实现一个校园网账号多台电脑可以同时上网路由器设置
  9. python实现石头剪刀布游戏
  10. java手机模式_Java使用建造者模式实现办理手机套餐功能详解