WPF教程十五:数据模板的使用(重发)
数据模板
数据模板是一段如何显示绑定在VM对象的XAML代码。数据模板可以包含任意元素的组合,基于Binding来显示不同的信息。
在实际的开发中数据模板的应用场景很多,同样一个控件可以根据不同的绑定源,根据以设置好的数据模板可以显示对应的不同的内容。
很多人用不好控件模板和数据模板,觉得有点混乱,大部分都是在追求7天入门WPF,或者直接就问有没有快速解决我目前问题的办法,等等。我也没有,但是数据模板其实比控件模板更好写,因为他的思路比较简单,就是这个数据,通过Binding后,界面上要显示成什么样。就这样。然后我们基于这个理解来延伸内容。
首先创建一个用于显示列表的ListBox我们模仿商店出售的商品。为了便于理解,所有的布局我都使简单的grid分割不涉及其他布局。
  <ListBox Name="ProductsListBox" MaxWidth="290" HorizontalContentAlignment="Stretch">
            <ListBox.ItemTemplate>
                <DataTemplate>
                        <Border Margin="5" CornerRadius="5" BorderThickness="1" BorderBrush="SteelBlue">
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                                <TextBlock Margin="3" FontWeight="Bold" Text="{Binding Path=Name}"/>
                                <Grid Grid.Row="1">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto"/>
                                            <ColumnDefinition Width="*"/>
                                        </Grid.ColumnDefinitions>
                                        <TextBlock  Text="单价:"/>
                                        <TextBlock Grid.Column="1" Text="{Binding Path=Price}"/>
                                    </Grid>
                                    <Grid Margin="1,0" Grid.Column="1">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto"/>
                                            <ColumnDefinition Width="*"/>
                                        </Grid.ColumnDefinitions>
                                        <TextBlock Text="剩余数量:"/>
                                        <TextBlock Grid.Column="1" Text="{Binding Path=Number}"/>
                                    </Grid>
                                </Grid>
                            </Grid>
                        </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
我们在ListBox中定义了ItemTemplate的DataTemplate。DataTemplate会再ListBox的ItemsSource绑定数据源后,拿出在DataTemplate中Binding的值,然后按照我们当前得DataTemplate来渲染。
我们定义在ItemTemplate下的数据模板,就是修改ListBox中的子对象如何显示。
完成代码如下:
xaml代码
<Window x:Class="HowtoUseDataTemplate.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:HowtoUseDataTemplate"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition  Width="auto"/>
            <ColumnDefinition Width="6*"/>
        </Grid.ColumnDefinitions>
        <ListBox Name="ProductsListBox" MaxWidth="290" HorizontalContentAlignment="Stretch">
            <ListBox.ItemTemplate>
                <DataTemplate>
                        <Border Margin="5" CornerRadius="5" BorderThickness="1" BorderBrush="SteelBlue">
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                                <TextBlock Margin="3" FontWeight="Bold" Text="{Binding Path=Name}"/>
                                <Grid Grid.Row="1">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto"/>
                                            <ColumnDefinition Width="*"/>
                                        </Grid.ColumnDefinitions>
                                        <TextBlock  Text="单价:"/>
                                        <TextBlock Grid.Column="1" Text="{Binding Path=Price}"/>
                                    </Grid>
                                    <Grid Margin="1,0" Grid.Column="1">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto"/>
                                            <ColumnDefinition Width="*"/>
                                        </Grid.ColumnDefinitions>
                                        <TextBlock Text="剩余数量:"/>
                                        <TextBlock Grid.Column="1" Text="{Binding Path=Number}"/>
                                    </Grid>
                                </Grid>
                            </Grid>
                        </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Border Margin="3" DataContext="{Binding ElementName=ProductsListBox,Path=SelectedItem}" Grid.Column="1" BorderBrush="AntiqueWhite" BorderThickness="1" CornerRadius="3">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="*"></RowDefinition>
                </Grid.RowDefinitions>
                <TextBlock  Text="名称:"/>
                <TextBlock Grid.Column="1" Text="{Binding Name}"/>
                <TextBlock Grid.Row="1" Text="单价:"/>
                <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Price}"/>
                <TextBlock Grid.Row="2" Text="数量:"/>
                <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Number}"/>
                <TextBlock Grid.Row="3" Text="介绍:"/>
                <TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding Introduce}"/>
            </Grid>
        </Border>
    </Grid>
</Window>
cs代码如下:
using System.Collections.Generic;
using System.Windows;
namespace HowtoUseDataTemplate
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        List<Product> products;
        public MainWindow()
        {
            InitializeComponent();
            products = new List<Product>()
            {
            new Product(){Name="火箭弹",Price=1000.00M, Number=5000,Introduce="这玩意要买大量的,便宜又方便、一次齐发。基本上就完成任务了。就是误差有点大。"},
            new Product(){Name="自动步枪(删除敏感字眼)",Price=300.00M, Number=5000 ,Introduce="单兵装备"},
            new Product(){ Name="爆震弹",Price=50.00M, Number=5000 ,Introduce="单兵装备"},
            new Product(){Name="防弹衣",Price=100.00M, Number=5000,Introduce="单兵装备"},
            new Product(){ Name="防弹头盔",Price=80.00M, Number=5000,Introduce="单兵装备"},
             new Product(){ Name="特别特别硬之真防弹头盔",Price=99999.00M, Number=5000,Introduce="单兵装备名字特别长"},
            };
            ProductsListBox.ItemsSource = products;
        }
    }
    public class Product
    {
        public int Number { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public string Introduce { get; set; }
    }
}

数据模板中还有一些常用比较方便的功能。比如数据触发器。和转换器,之前讲过。在之前讲了属性触发器、事件触发器。但是数据触发器没讲,这里讲一下。
(删除敏感字眼) 举个例子,火箭弹热卖了。我们虚拟出来的软件产品既然包含了这些,产品经理就提出来要添加一个热卖产品的提醒功能,在产品名称旁边添加一个热卖品的红色hot斜体的文字显示,同时文字也要变成红色。
回想到我们刚才的数据模板,使用数据触发器来实现热卖品显示hot功能。在实体中添加是否是热卖品属性。实现转换器、实现数据触发器。
1)再工程下添加Converter文件夹
编写HotBoolToVisibilityConverter类,代码如下:
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace HowtoUseDataTemplate.Converter
{
    public class HotBoolToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is bool b)
            {
                if (b)
                {
                    return Visibility.Visible;
                }
            }
            return Visibility.Collapsed;
        }
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
回到主窗体找到Priduct类,添加IsHot属性。设置默认值为false。
再Products中设置每个对象是否是热卖。完整代码如下:
using System.Collections.Generic;
using System.Windows;
namespace HowtoUseDataTemplate
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        List<Product> products;
        public MainWindow()
        {
            InitializeComponent();
            products = new List<Product>()
            {
            new Product(){Name="火箭弹",IsHot=true, Price=1000.00M, Number=5000,Introduce="这玩意要买大量的,便宜又方便、一次齐发。基本上就完成任务了。就是误差有点大。"},
            new Product(){Name="自动步枪(删除敏感字眼)",Price=300.00M, Number=5000 ,Introduce="单兵装备"},
            new Product(){ Name="爆震弹",Price=50.00M, Number=5000 ,Introduce="单兵装备"},
            new Product(){Name="防弹衣",Price=100.00M, Number=5000,Introduce="单兵装备"},
            new Product(){ Name="防弹头盔",Price=80.00M, Number=5000,Introduce="单兵装备"},
             new Product(){ Name="特别特别硬之真防弹头盔",Price=99999.00M, Number=5000,Introduce="单兵装备名字特别长"},
            };
            ProductsListBox.ItemsSource = products;
        }
    }
    public class Product
    {
        public int Number { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public string Introduce { get; set; }
        public bool IsHot { get; set; } = false;
    }
}
最后回到主窗体的XAML文件下,添加转换器的引用和资源。
 xmlns:converter="clr-namespace:HowtoUseDataTemplate.Converter"
    <Window.Resources>
        <converter:HotBoolToVisibilityConverter x:Key="HotBoolToVisibilityConverter"/>
    </Window.Resources>
找到数据模板中的商品名称,重新设计Grid布局并添加一个hot文本控件。
<Grid>
      <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto"/>
      <ColumnDefinition Width="*"/>
      </Grid.ColumnDefinitions>
      <TextBlock x:Name="NameTextBlock" Margin="3" FontWeight="Bold" Text="{Binding Path=Name}"/>
      <TextBlock Margin="0,2,2,2" Visibility="{Binding IsHot,Converter={StaticResource HotBoolToVisibilityConverter}}" FontSize="10" Grid.Column="1" FontStyle="Italic" Text="Hot" Foreground="Red"/>
</Grid>
写一个数据触发器,当IsHot等于true的时候。去找模板中Name=NameText的控件,设置他的Foreground颜色属性为红色,
   <DataTemplate.Triggers>
                        <DataTrigger Binding="{Binding Path=IsHot}" Value="True">
                            <Setter Property="TextBlock.Foreground" TargetName="NameTextBlock" Value="Red"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
XAML完整代码如下:
<Window x:Class="HowtoUseDataTemplate.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:converter="clr-namespace:HowtoUseDataTemplate.Converter"
        xmlns:local="clr-namespace:HowtoUseDataTemplate"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <converter:HotBoolToVisibilityConverter x:Key="HotBoolToVisibilityConverter"/>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition  Width="auto"/>
            <ColumnDefinition Width="6*"/>
        </Grid.ColumnDefinitions>
        <ListBox Name="ProductsListBox" MaxWidth="290" HorizontalContentAlignment="Stretch">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <DataTemplate.Triggers>
                        <DataTrigger Binding="{Binding Path=IsHot}" Value="True">
                            <Setter Property="TextBlock.Foreground" TargetName="NameTextBlock" Value="Red"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                        <Border Margin="5" CornerRadius="5" BorderThickness="1" BorderBrush="SteelBlue">
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <TextBlock x:Name="NameTextBlock" Margin="3" FontWeight="Bold" Text="{Binding Path=Name}"/>
                                <TextBlock Margin="0,2,2,2" Visibility="{Binding IsHot,Converter={StaticResource HotBoolToVisibilityConverter}}" FontSize="10" Grid.Column="1" FontStyle="Italic" Text="Hot" Foreground="Red"/>
                            </Grid>
                                <Grid Grid.Row="1">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto"/>
                                            <ColumnDefinition Width="*"/>
                                        </Grid.ColumnDefinitions>
                                        <TextBlock  Text="单价:"/>
                                        <TextBlock Grid.Column="1" Text="{Binding Path=Price}"/>
                                    </Grid>
                                    <Grid Margin="1,0" Grid.Column="1">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto"/>
                                            <ColumnDefinition Width="*"/>
                                        </Grid.ColumnDefinitions>
                                        <TextBlock Text="剩余数量:"/>
                                        <TextBlock Grid.Column="1" Text="{Binding Path=Number}"/>
                                    </Grid>
                                </Grid>
                            </Grid>
                        </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Border Margin="3" DataContext="{Binding ElementName=ProductsListBox,Path=SelectedItem}" Grid.Column="1" BorderBrush="AntiqueWhite" BorderThickness="1" CornerRadius="3">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="*"></RowDefinition>
                </Grid.RowDefinitions>
                <TextBlock  Text="名称:"/>
                <TextBlock Grid.Column="1" Text="{Binding Name}"/>
                <TextBlock Grid.Row="1" Text="单价:"/>
                <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Price}"/>
                <TextBlock Grid.Row="2" Text="数量:"/>
                <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Number}"/>
                <TextBlock Grid.Row="3" Text="介绍:"/>
                <TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding Introduce}"/>
            </Grid>
        </Border>
    </Grid>
</Window>
效果如下,这样我们就实现了热卖的功能。通过数据模板只修改了很少一部分内容。

我们去看上面的XAML代码,我们现在只有一个简单的ListBox重写样式,就这么多内容需要写,那如果界面上内容特别多,代码不是很难读吗,我们接下来把代码拆出去。把DataTemplate写到当前窗体的Resources中。然后再ListBox中设置ItemTemplate等于我们再资源中定义的数据模板。代码如下:
<Window x:Class="HowtoUseDataTemplate.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:converter="clr-namespace:HowtoUseDataTemplate.Converter"
        xmlns:local="clr-namespace:HowtoUseDataTemplate"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <converter:HotBoolToVisibilityConverter x:Key="HotBoolToVisibilityConverter"/>
        <DataTemplate x:Key="ProductItemTemplate">
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=IsHot}" Value="True">
                    <Setter Property="TextBlock.Foreground" TargetName="NameTextBlock" Value="Red"/>
                </DataTrigger>
            </DataTemplate.Triggers>
            <Border Margin="5" CornerRadius="5" BorderThickness="1" BorderBrush="SteelBlue">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock x:Name="NameTextBlock" Margin="3" FontWeight="Bold" Text="{Binding Path=Name}"/>
                        <TextBlock Margin="0,2,2,2" Visibility="{Binding IsHot,Converter={StaticResource HotBoolToVisibilityConverter}}" FontSize="10" Grid.Column="1" FontStyle="Italic" Text="Hot" Foreground="Red"/>
                    </Grid>
                    <Grid Grid.Row="1">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock  Text="单价:"/>
                            <TextBlock Grid.Column="1" Text="{Binding Path=Price}"/>
                        </Grid>
                        <Grid Margin="1,0" Grid.Column="1">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Text="剩余数量:"/>
                            <TextBlock Grid.Column="1" Text="{Binding Path=Number}"/>
                        </Grid>
                    </Grid>
                </Grid>
            </Border>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition  Width="auto"/>
            <ColumnDefinition Width="6*"/>
        </Grid.ColumnDefinitions>
        <ListBox Name="ProductsListBox" MaxWidth="290" HorizontalContentAlignment="Stretch" ItemTemplate="{StaticResource ProductItemTemplate}">
        </ListBox>
        <Border Margin="3" DataContext="{Binding ElementName=ProductsListBox,Path=SelectedItem}" Grid.Column="1" BorderBrush="AntiqueWhite" BorderThickness="1" CornerRadius="3">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="*"></RowDefinition>
                </Grid.RowDefinitions>
                <TextBlock  Text="名称:"/>
                <TextBlock Grid.Column="1" Text="{Binding Name}"/>
                <TextBlock Grid.Row="1" Text="单价:"/>
                <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Price}"/>
                <TextBlock Grid.Row="2" Text="数量:"/>
                <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Number}"/>
                <TextBlock Grid.Row="3" Text="介绍:"/>
                <TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding Introduce}"/>
            </Grid>
        </Border>
    </Grid>
</Window>
这样Grid下的内容就少了很多,结构就清晰了一些。不建议把DataTemplate放到单独的文件夹中,因为如果App初始化的时候就加载了这些内容的话。可能targetType会影响到所有的使用了这个类的对象。但是其实也有x:key这个可以控制,所以这里具体看需要把。觉得怎么合适怎么来,反正主要的目标都是解耦。
再上面点击更换Item的时候有个比较讨厌的地方,选中的对象有一个蓝色的底色改变了,这个是ItemContainerSytle的内容。修改ListBox代码如下:
 <ListBox Name="ProductsListBox" MaxWidth="290" HorizontalContentAlignment="Stretch" ItemTemplate="{StaticResource ProductItemTemplate}">
            <ListBox.ItemContainerStyle>
                <Style>
                    <Setter Property="ItemsControl.Padding" Value="0"/>
                    <Style.Triggers>
                        <Trigger Property="ListBoxItem.IsSelected" Value="True">
                            <Setter Property="ListBoxItem.Background" Value="	#84C1FF"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
上面的数据模板中最外层的Border 外面嵌套一层Grid 同时背景色设置为和Listbox背景色一样,就可以拉。
这篇就写这么多。到这篇为止就打算基础部分结束了,下篇讲MVVM,IOC。就开始进入财务软件的项目实战,因为剩下一些没讲的章节,我整理了一下,大概是Page、Window、控件、TreeView、DataGrid等等。我觉得讲控件不属于入门知识,因为控件实际使用中包含了VM、数据模板、控件模板、Style还有更加深入的列表虚拟化、和数据虚拟化等等。还有怎么调试并分析问题等等。所以这里就不打算讲了。以后作为WPF技巧相关的文章,去梳理这些知识点。
我创建了一个C#相关的交流群。用于分享学习资料和讨论问题,欢迎有兴趣的小伙伴:QQ群:542633085
WPF教程十五:数据模板的使用(重发)的更多相关文章
- 无废话ExtJs 入门教程十五[员工信息表Demo:AddUser]
		
无废话ExtJs 入门教程十五[员工信息表Demo:AddUser] extjs技术交流,欢迎加群(201926085) 前面我们共介绍过10种表单组件,这些组件是我们在开发过程中最经常用到的,所以一 ...
 - webpack4 系列教程(十五):开发模式与webpack-dev-server
		
作者按:因为教程所示图片使用的是 github 仓库图片,网速过慢的朋友请移步<webpack4 系列教程(十五):开发模式与 webpack-dev-server>原文地址.更欢迎来我的 ...
 - RabbitMQ入门教程(十五):普通集群和镜像集群
		
原文:RabbitMQ入门教程(十五):普通集群和镜像集群 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.c ...
 - WPF教程十二:了解自定义控件的基础和自定义无外观控件
		
这一篇本来想先写风格主题,主题切换.自定义配套的样式.但是最近加班.搬家.新租的房子打扫卫生,我家宝宝6月中旬要出生协调各种的事情,导致了最近精神状态不是很好,又没有看到我比较喜欢的主题风格去模仿的, ...
 - Unity3D脚本中文系列教程(十五)
		
http://dong2008hong.blog.163.com/blog/static/4696882720140322449780/ Unity3D脚本中文系列教程(十四) ◆ LightRend ...
 - Django(十五)模板详解:模板标签、过滤器、模板注释、模板继承、html转义
		
一.模板的基础配置及使用 [参考]https://docs.djangoproject.com/zh-hans/3.0/topics/templates/ 作为Web框架,Django提供了模板,用于 ...
 - Wix 安装部署教程(十五) --CustomAction的七种用法
		
在WIX中,CustomAction用来在安装过程中执行自定义行为.比如注册.修改文件.触发其他可执行文件等.这一节主要是介绍一下CustomAction的7种用法. 在此之前要了解InstallEx ...
 - WebGL简易教程(十五):加载gltf模型
		
目录 1. 概述 2. 实例 2.1. 数据 2.2. 程序 2.2.1. 文件读取 2.2.2. glTF格式解析 2.2.3. 初始化顶点缓冲区 2.2.4. 其他 3. 结果 4. 参考 5. ...
 - Spring Boot2 系列教程 (十五) | 服务端参数校验之一
		
估计很多朋友都认为参数校验是客户端的职责,不关服务端的事.其实这是错误的,学过 Web 安全的都知道,客户端的验证只是第一道关卡.它的参数验证并不是安全的,一旦被有心人抓到可乘之机,他就可以有各种方法 ...
 
随机推荐
- Hadoop 基石HDFS 一文了解文件存储系统
			
@ 目录 前言:浅谈Hadoop Hadoop的发展历程 1.1 Hadoop产生背景 1.引入HDFS设计 1.1 HDFS主要特性 2.HDFS体系结构 HDFS工作流程机制 1.各个节点是如何互 ...
 - Spring Mvc Long类型精度丢失
			
背景 在使用Spring Boot Mvc的项目中,使用Long类型作为id的类型,但是当前端使用Number类型接收Long类型数据时,由于前端精度问题,会导致Long类型数据转换为Number类型 ...
 - bat脚本总结
			
1.修改密码 @echo off set /p b=请输入新密码: net user %username% %b% echo 密码修改成功 %b% 请牢记你的密码 pause 2.删除hosts文件并 ...
 - gasshopper之python电池输出dict结构
			
问题:gh 直接用 panel 是无法直接输出字典结构的 故需要用 zip() 函数将字典的keys() values() 组成一个元组,可以直接输出: 实例: dict = {} for i in ...
 - TVM编译机器学习到 WASM 和 WebGPU
			
TVM编译机器学习到 WASM 和 WebGPU TLDR TVM 深度学习编译器对 WASM 和 WebGPU 的支持.实验表明,TVM 的 WebGPU 后端在将模型部署到 Web 时可以接近原生 ...
 - Numba实时变量分析
			
Numba实时变量分析 Numba使用引用计数进行垃圾回收,这是一种需要编译器配合的技术.Numba IR对必须插入decref的位置进行编码.这些位置通过实时变量分析确定.相应的源代码是https: ...
 - Pipe Utilization管道利用率
			
Pipe Utilization管道利用率 概述 CUDA设备的每个流式多处理器(SM)都具有许多专门用于执行特定任务的硬件单元.在芯片级,这些单元提供执行管道,翘曲调度程序将指令发送到这些管道.例如 ...
 - 重新整理 mysql 基础篇————— 介绍mysql[一]
			
前言 准备整理mysql的基础篇了,前面整理了sql语句序列的的<sql 语句系列(八百章)>,感觉很多用不上,就停下来了,后续还是会继续整理. mysql 基础篇主要是对一些基础进行整理 ...
 - NOIP2018初赛普及组原题&题解
			
NOIP2018初赛普及组原题&题解 目录 NOIP2018初赛普及组原题&题解 原题&答案 题解 单项选择题 第$1$题 第$2$题 第$3$题 第$4$题 第$5$题 第$ ...
 - Fedora 34成哑巴了?
			
原由 前几天刚更新了Fedora34,完全沉浸在Gnome40的喜悦中.但是今天用耳机听Apple Music的时候完全傻了,音量控制旋钮调了半天也没有声音,难道声卡坏了?于是,我试探性的用Parro ...