WPF第一个DEMO
最近学习WPF,由于此前并未接触过C#相关项目。本次学习,分两个部分,该部分使用常规设计方式。即使用非MVVM设计模式。后续会重写一个MVVM模式的代码。
预览效果
本次主要实现对学生的增删改查操作。
页面效果如下:
一、创建项目
本次使用的是Visual Studio 2017 不同的版本界面可能有些不同。
打开Visual Studio 依次点击:文件 ->新建->项目
选择Visual C# ->Windows 桌面 ->WPF应用(.NET Framework)
二、创建查询列表
先新建Student类
右击MyFirstWPFDemo->添加-> 类新建Student.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyFirstWPFDemo
{
public class Student : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int id;
private string name;
private int age;
private Sex sex;
private string hobby;
public static Student GetStudent()
{
return new Student();
}
private Student()
{
}
public Student(int id, string name, int age, Sex sex, string hobby)
{
this.Id = id;
this.Name = name;
this.Age = age;
this.Sex = sex;
this.Hobby = hobby;
}
public int Id
{
get => id;
set
{
id = value;
OnPropertyChanged("Id");
}
}
public string Name
{
get => name;
set
{
name = value;
OnPropertyChanged("Name");
}
}
public int Age
{
get => age;
set
{
age = value;
OnPropertyChanged("Age");
}
}
public Sex Sex
{
get => sex;
set
{
sex = value; OnPropertyChanged("Sex");
}
}
public string Hobby
{
get => hobby;
set
{
hobby = value; OnPropertyChanged("Hobby");
}
}
protected internal virtual void OnPropertyChanged(string propertyName)
{
/**
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
**/
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public override string ToString()
{
return "{id=" + Id + " ,name=" + Name + " ,age= " + Age + " ,sex=" + Sex + " , hobby= " + Hobby + "} ";
}
public Student Clone()
{
Student student = new Student(this.id, this.name, this.age, this.sex, this.hobby);
return student;
}
}
}
新建Sex.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyFirstWPFDemo
{
public enum Sex
{
男,
女
}
}
新建StudentDB.cs 模拟本地数据存储
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyFirstWPFDemo
{
public class StudentDB
{
private static ObservableCollection<Student> students = new ObservableCollection<Student>()
{
new Student(1,"张三", 23, Sex.男, "乒乓球"),
new Student(2,"李四", 20, Sex.男, "游泳"),
new Student(3,"丽丽", 18, Sex.女, "跳舞")
};
public static ObservableCollection<Student> QueryStudent()
{
ObservableCollection<Student> stus = new ObservableCollection<Student>();
foreach (Student stu in StudentDB.students)
{
stus.Add((Student)stu.Clone());
}
return stus;
}
public static ObservableCollection<Student> QueryStudent(string search)
{
ObservableCollection<Student> stus = new ObservableCollection<Student>();
foreach (Student stu in StudentDB.students)
{
if (string.IsNullOrEmpty(search))
{
stus.Add((Student)stu.Clone());
}
else
{
if (stu.Name.Contains(search))
{
stus.Add((Student)stu.Clone());
}
}
}
return stus;
}
public static ObservableCollection<Student> Add(Student student)
{
StudentDB.students.Add(student);
ObservableCollection<Student> stus = new ObservableCollection<Student>();
foreach (Student stu in StudentDB.students)
{
stus.Add((Student)stu.Clone());
}
return stus;
}
public static ObservableCollection<Student> Delete(Student student)
{
//移除StudentDB.students值
for (int i = 0; i < StudentDB.students.Count; i++)
{
if (StudentDB.students[i].Id == student.Id)
{
StudentDB.students.Remove(StudentDB.students[i]);
break;
}
}
ObservableCollection<Student> stus = new ObservableCollection<Student>();
foreach (Student stu in StudentDB.students)
{
stus.Add((Student)stu.Clone());
}
return stus;
}
public static ObservableCollection<Student> Edit(Student student)
{
//修改 StudentDB.students值
for (int i = 0; i < StudentDB.students.Count; i++)
{
if (StudentDB.students[i].Id == student.Id)
{
//修改
StudentDB.students[i] = student;
break;
}
}
ObservableCollection<Student> stus = new ObservableCollection<Student>();
foreach (Student stu in StudentDB.students)
{
stus.Add((Student)stu.Clone());
}
return stus;
}
public static int GetStudentDBId()
{
int tempId = 0;
foreach (Student stu in StudentDB.students)
{
if (stu.Id >= tempId)
{
tempId = stu.Id;
}
}
tempId++;
return tempId;
}
}
}
添加背景图片,在根目录新建文件夹Resources, 将背景图片background.png 放入该目录。
编辑MainWindow.xaml
<Window x:Class="MyFirstWPFDemo.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:MyFirstWPFDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style x:Key="TextBlockStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="楷体"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Foreground" Value="OrangeRed"/>
<Setter Property="FontWeight" Value="Light" />
</Style>
</Window.Resources>
<Grid>
<Grid.Background>
<ImageBrush ImageSource="Resources/background.png" />
</Grid.Background>
<Grid >
<!--行-->
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="50"/>
<RowDefinition Height="300"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Center" >
</StackPanel>
<StackPanel Grid.Row="1" Margin="5">
</StackPanel>
<DataGrid Grid.Row="2" Name="listStudent" ItemsSource="{Binding}" AutoGenerateColumns="False" Height="300">
<DataGrid.Columns >
<DataGridTextColumn Header="Id" Width="100" Binding="{Binding Id ,Mode=OneWay}"/>
<DataGridTextColumn Header="姓名" Width="100" Binding="{Binding Name ,Mode=OneWay}"/>
<DataGridTextColumn Header="年龄" Width="100" Binding="{Binding Age ,Mode=OneWay}"/>
<DataGridTextColumn Header="性别" Width="100" Binding="{Binding Sex ,Mode=OneWay}"/>
<DataGridTextColumn Header="爱好" Width="Auto" MinWidth="150" Binding="{Binding Hobby}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Grid>
</Window>
编辑MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MyFirstWPFDemo
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private ObservableCollection<Student> students;
public MainWindow()
{
InitializeComponent();
students = StudentDB.QueryStudent();
this.listStudent.DataContext = students;
}
}
}
效果如图所示:
三、添加查询功能
给MainWindow.xaml 添加查询功能
<TabPanel Name="tabPanel">
<TextBlock Text="用户姓名:"
Style="{StaticResource TextBlockStyle}"/>
<TextBox Name="searchValue" Width="100" />
<Button Name="SearchButton" Content="查询"
Click="Search_Click" HorizontalAlignment="Right"/>
</TabPanel>
完整代码为:
<Window x:Class="MyFirstWPFDemo.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:MyFirstWPFDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style x:Key="TextBlockStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="楷体"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Foreground" Value="OrangeRed"/>
<Setter Property="FontWeight" Value="Light" />
</Style>
</Window.Resources>
<Grid>
<Grid.Background>
<ImageBrush ImageSource="Resources/background.png" />
</Grid.Background>
<Grid >
<!--行-->
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="50"/>
<RowDefinition Height="300"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Center" >
<TabPanel Name="tabPanel">
<TextBlock Text="用户姓名:"
Style="{StaticResource TextBlockStyle}"/>
<TextBox Name="searchValue" Width="100" />
<Button Name="SearchButton" Content="查询"
Click="Search_Click" HorizontalAlignment="Right"/>
</TabPanel>
</StackPanel>
<StackPanel Grid.Row="1" Margin="5">
</StackPanel>
<DataGrid Grid.Row="2" Name="listStudent" ItemsSource="{Binding}" AutoGenerateColumns="False" Height="300">
<DataGrid.Columns >
<DataGridTextColumn Header="Id" Width="100" Binding="{Binding Id ,Mode=OneWay}"/>
<DataGridTextColumn Header="姓名" Width="100" Binding="{Binding Name ,Mode=OneWay}"/>
<DataGridTextColumn Header="年龄" Width="100" Binding="{Binding Age ,Mode=OneWay}"/>
<DataGridTextColumn Header="性别" Width="100" Binding="{Binding Sex ,Mode=OneWay}"/>
<DataGridTextColumn Header="爱好" Width="Auto" MinWidth="150" Binding="{Binding Hobby}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Grid>
</Window>
添加Search_Click点击事件
private void Search_Click(object sender, RoutedEventArgs e)
{
this.students = StudentDB.QueryStudent(this.searchValue.Text);
this.listStudent.DataContext = students;
}
效果如图所示:
四、添加列表按钮
列表DataGrid.Columns中添加一下代码
<DataGridTemplateColumn Header="操作">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<Button Name="Edit" Content="修改" Click="Edit_Click" />
<Button Name="Delete" Content="删除" Click="Delete_Click" />
<Button Name="Test" Content="路由事件" Background="YellowGreen" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
完整代码为:
<Window x:Class="MyFirstWPFDemo.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:MyFirstWPFDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style x:Key="TextBlockStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="楷体"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Foreground" Value="OrangeRed"/>
<Setter Property="FontWeight" Value="Light" />
</Style>
</Window.Resources>
<Grid>
<Grid.Background>
<ImageBrush ImageSource="Resources/background.png" />
</Grid.Background>
<Grid >
<!--行-->
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="50"/>
<RowDefinition Height="300"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Center" >
<TabPanel Name="tabPanel">
<TextBlock Text="用户姓名:" Style="{StaticResource TextBlockStyle}"/>
<TextBox Name="searchValue" Width="100" />
<Button Name="SearchButton" Content="查询" Click="Search_Click" HorizontalAlignment="Right"/>
</TabPanel>
</StackPanel>
<StackPanel Grid.Row="1" Margin="5"></StackPanel>
<DataGrid Grid.Row="2" Name="listStudent" ItemsSource="{Binding}" AutoGenerateColumns="False" Height="300">
<DataGrid.Columns >
<DataGridTextColumn Header="Id" Width="100" Binding="{Binding Id ,Mode=OneWay}"/>
<DataGridTextColumn Header="姓名" Width="100" Binding="{Binding Name ,Mode=OneWay}"/>
<DataGridTextColumn Header="年龄" Width="100" Binding="{Binding Age ,Mode=OneWay}"/>
<DataGridTextColumn Header="性别" Width="100" Binding="{Binding Sex ,Mode=OneWay}"/>
<DataGridTextColumn Header="爱好" Width="Auto" MinWidth="150" Binding="{Binding Hobby}"/>
<DataGridTemplateColumn Header="操作">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<Button Name="Edit" Content="修改" Click="Edit_Click" />
<Button Name="Delete" Content="删除" Click="Delete_Click" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Grid>
</Window>
添加后端代码:
private void Edit_Click(object sender, RoutedEventArgs e) {
}
private void Delete_Click(object sender, RoutedEventArgs e) {
this.students = StudentDB.Delete((Student) this.listStudent.SelectedItem);
this.students = StudentDB.QueryStudent(this.searchValue.Text);
this.listStudent.DataContext = students;
}
现在已经完成修改,删除按钮添加。此时仅删除按钮有效果,修改按钮暂时还没有效果。
效果,如图所示:
五、实现修改功能
新建一个StudentEditWindow.xaml 窗口。
右键MyFirstWPFDemo -> 添加 -> 窗口
编辑页前端代码如下:
<Window x:Class="MyFirstWPFDemo.StudentEditWindow"
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:MyFirstWPFDemo"
mc:Ignorable="d"
Title="StudentEditWindow" Height="380" Width="600">
<Window.Resources>
<local:SexToBoolConverter x:Key="SexToBoolConverter"></local:SexToBoolConverter>
</Window.Resources>
<Grid>
<Grid.Background>
<ImageBrush ImageSource="Resources/background.png" />
</Grid.Background>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="100"/>
<RowDefinition Height="100"/>
<RowDefinition Height="Auto" MinHeight="90"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="Auto" MinWidth="150"/>
</Grid.ColumnDefinitions>
<TabPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="姓名:" HorizontalAlignment="Left" />
<TextBlock Text="{Binding Name}" Width="80" HorizontalAlignment="Left" />
</TabPanel>
<TabPanel Grid.Row="1" Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Center" >
<TabPanel>
<TextBlock Text="年龄:"/>
<TextBox Text="{Binding Age}" Width="100"/>
</TabPanel>
</TabPanel>
<TabPanel Grid.Row="2" Grid.ColumnSpan="1" HorizontalAlignment="Center" VerticalAlignment="Center" >
<TabPanel>
<TextBlock Text="爱好:"/>
<TextBox Text="{Binding Hobby}" Width="Auto" MinWidth="50"/>
</TabPanel>
</TabPanel>
<StackPanel Grid.Row="2" Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Center" >
<TabPanel>
<RadioButton GroupName="Sex" IsChecked="{Binding Sex,Converter={StaticResource SexToBoolConverter},ConverterParameter=0}">男</RadioButton>
<RadioButton GroupName="Sex" IsChecked="{Binding Sex,Converter={StaticResource SexToBoolConverter},ConverterParameter=1}">女</RadioButton>
</TabPanel>
</StackPanel>
<TabPanel Grid.Row="3" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="2" >
<Button Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="1" Content="确定" Click="Submit_Click" />
<TextBlock Width="20"/>
<Button Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="1" Content="取消" Click="Cancel_Click"/>
</TabPanel>
</Grid>
</Grid>
</Window>
编辑页后端代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace StudentDemo2
{
/// <summary>
/// StudentEditWindow.xaml 的交互逻辑
/// </summary>
public partial class StudentEditWindow : Window
{
private object selected;
public StudentEditWindow()
{
InitializeComponent();
}
public StudentEditWindow(object selectedItem) : this()
{
this.selected = selectedItem;
this.DataContext = ((Student)selectedItem).Clone();
}
private void Submit_Click(object sender, RoutedEventArgs e)
{
Student stu =(Student)this.selected ;
stu.Hobby = ((Student)this.DataContext).Hobby;
stu.Sex = ((Student)this.DataContext).Sex;
stu.Age = ((Student)this.DataContext).Age;
this.Close();
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
}
添加转换器 SexToBoolConverter.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace MyFirstWPFDemo
{
class SexToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Sex s = (Sex)value;
return s == (Sex)int.Parse(parameter.ToString());
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool isChecked = (bool)value;
if (!isChecked)
{
return null;
}
return (Sex)int.Parse(parameter.ToString());
}
}
}
完善MainWindow.xaml.cs 中的Edit_Click方法
private void Edit_Click(object sender, RoutedEventArgs e) {
Student stu = (Student) this.listStudent.SelectedItem;
StudentEditWindow studentEdit = new StudentEditWindow(stu);
studentEdit.ShowDialog();
this.students = StudentDB.Edit(stu);
this.students = StudentDB.QueryStudent(this.searchValue.Text);
this.listStudent.DataContext = students;
}
此时,列表中的修改按钮生效,效果如图所示
六、实现新增功能
在 主窗口MainWindow.xaml 添加新增按钮
<StackPanel Grid.Row="1" Margin="5">
<Button Name="Add" Content="新增" Click="Add_Click" HorizontalAlignment="Left"/>
</StackPanel>
后端MainWindow.xaml.cs 新增方法Add_Click
private void Add_Click(object sender, RoutedEventArgs e) {
StudentAddWindow studentAdd = new StudentAddWindow();
studentAdd.ShowDialog();
Student stu = (Student) studentAdd.GetTempStudent();
if (stu != null) {
stu.Id = StudentDB.GetStudentDBId();
this.students = StudentDB.Add(stu);
this.listStudent.DataContext = students;
}
}
新增 StudentAddWindow.xaml 窗体。
前端代码为:
<Window x:Class="MyFirstWPFDemo.StudentAddWindow" 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:MyFirstWPFDemo" mc:Ignorable="d" Title="StudentAddWindow"
Height="380" Width="600">
<Window.Resources>
<local:SexToBoolConverter x:Key="SexToBoolConverter">
</local:SexToBoolConverter>
</Window.Resources>
<Grid>
<Grid.Background>
<ImageBrush ImageSource="Resources/background.png" />
</Grid.Background>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="100" />
<RowDefinition Height="100" />
<RowDefinition Height="Auto" MinHeight="90" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="Auto" MinWidth="150" />
</Grid.ColumnDefinitions>
<TabPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="姓名:" HorizontalAlignment="Left" />
<TextBox Text="{Binding Name}" Width="80" HorizontalAlignment="Left" />
</TabPanel>
<TabPanel Grid.Row="1" Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Center">
<TabPanel>
<TextBlock Text="年龄:" />
<TextBox Text="{Binding Age}" Width="100" />
</TabPanel>
</TabPanel>
<TabPanel Grid.Row="2" Grid.ColumnSpan="1" HorizontalAlignment="Center"
VerticalAlignment="Center">
<TabPanel>
<TextBlock Text="爱好:" />
<TextBox Text="{Binding Hobby}" Width="Auto" MinWidth="50" />
</TabPanel>
</TabPanel>
<StackPanel Grid.Row="2" Grid.Column="3" HorizontalAlignment="Center"
VerticalAlignment="Center">
<TabPanel>
<RadioButton GroupName="Sex" IsChecked="{Binding Sex,Converter={StaticResource SexToBoolConverter},ConverterParameter=0}">
男
</RadioButton>
<RadioButton GroupName="Sex" IsChecked="{Binding Sex,Converter={StaticResource SexToBoolConverter},ConverterParameter=1}">
女
</RadioButton>
</TabPanel>
</StackPanel>
<TabPanel Grid.Row="3" HorizontalAlignment="Center" VerticalAlignment="Center"
Grid.Column="2">
<Button Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="1" Content="确定"
Click="Submit_Click" />
<TextBlock Width="20" />
<Button Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="1" Content="取消"
Click="Cancel_Click" />
</TabPanel>
</Grid>
</Grid>
</Window>
后端代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace MyFirstWPFDemo {
/// <summary>
/// StudentAddWindow.xaml 的交互逻辑
/// </summary>
public partial class StudentAddWindow: Window {
private Student student;
public StudentAddWindow() {
InitializeComponent();
this.DataContext = Student.GetStudent();
}
private void Submit_Click(object sender, RoutedEventArgs e) {
this.student = (Student) this.DataContext;
this.Close();
}
private void Cancel_Click(object sender, RoutedEventArgs e) {
this.Close();
}
public Student GetTempStudent() {
return this.student;
}
}
}
效果如图所示:
七、实现查询框清除功能
该处使用命令方式清除查询框,该处代码相对较难。可以与普通点击事件查询按钮对比。
MainWindow.xaml中,在查询按钮旁边添加清除按钮
<Button Name="ClearButton" Content="命令方式清除" HorizontalAlignment="Right"/>
添加后端代码:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MyFirstWPFDemo {
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow: Window {
private ObservableCollection < Student > students;
//申明并定义命令
private RoutedCommand clearCmd = new RoutedCommand("Clear", typeof(MainWindow));
public MainWindow() {
InitializeComponent();
//命令初始化
InitialiizeCommand();
students = StudentDB.QueryStudent();
this.listStudent.DataContext = students;
}
//初始化命令
private void InitialiizeCommand() {
//把命令赋值给命令源(发送者)并指定快捷方键
this.ClearButton.Command = this.clearCmd;
this.clearCmd.InputGestures.Add(new KeyGesture(Key.C, ModifierKeys.Alt));
//指定命令目标
this.ClearButton.CommandTarget = this.searchValue;
//创建命令联
CommandBinding cb = new CommandBinding();
cb.Command = this.clearCmd; //只关注与clearCmd相关事件
cb.CanExecute += new CanExecuteRoutedEventHandler(Cb_CanExecute);
cb.Executed += new ExecutedRoutedEventHandler(Cb_Executed);
//把命令关联安置到外围控件上
this.tabPanel.CommandBindings.Add(cb);
}
//当探测命令是否可以执行是,此方法被调用
void Cb_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
if (string.IsNullOrEmpty(this.searchValue.Text)) {
e.CanExecute = false;
} else {
e.CanExecute = true;
}
//避免继续向上传而降低程序性能
e.Handled = true;
}
void Cb_Executed(object sender, ExecutedRoutedEventArgs e) {
this.searchValue.Clear();
this.listStudent.DataContext =
StudentDB.QueryStudent(this.searchValue.Text);
//避免继续向上传而降低程序性能
e.Handled = true;
}
private void Search_Click(object sender, RoutedEventArgs e) {
this.students = StudentDB.QueryStudent(this.searchValue.Text);
this.listStudent.DataContext = students;
}
private void Add_Click(object sender, RoutedEventArgs e) {
StudentAddWindow studentAdd = new StudentAddWindow();
studentAdd.ShowDialog();
Student stu = (Student) studentAdd.GetTempStudent();
if (stu != null) {
stu.Id = StudentDB.GetStudentDBId();
this.students = StudentDB.Add(stu);
this.listStudent.DataContext = students;
}
}
private void Edit_Click(object sender, RoutedEventArgs e) {
Student stu = (Student) this.listStudent.SelectedItem;
StudentEditWindow studentEdit = new StudentEditWindow(stu);
studentEdit.ShowDialog();
this.students = StudentDB.Edit(stu);
this.students = StudentDB.QueryStudent(this.searchValue.Text);
this.listStudent.DataContext = students;
}
private void Delete_Click(object sender, RoutedEventArgs e) {
this.students = StudentDB.Delete((Student) this.listStudent.SelectedItem);
this.students = StudentDB.QueryStudent(this.searchValue.Text);
this.listStudent.DataContext = students;
}
}
}
效果如图所示:
八、实现列表路由事件按钮
MainWindow.xaml主窗体列表中,在删除按钮位置,新增路由按钮。
同时在DataGrid上添加路由点击事件RouteClicked事件。
代码如下
<DataGrid Grid.Row="2" Name="listStudent" ItemsSource="{Binding}" AutoGenerateColumns="False"
Height="300" ButtonBase.Click="RouteClicked">
<DataGrid.Columns>
<DataGridTextColumn Header="Id" Width="100" Binding="{Binding Id ,Mode=OneWay}"
/>
<DataGridTextColumn Header="姓名" Width="100" Binding="{Binding Name ,Mode=OneWay}"
/>
<DataGridTextColumn Header="年龄" Width="100" Binding="{Binding Age ,Mode=OneWay}"
/>
<DataGridTextColumn Header="性别" Width="100" Binding="{Binding Sex ,Mode=OneWay}"
/>
<DataGridTextColumn Header="爱好" Width="Auto" MinWidth="150" Binding="{Binding Hobby}"
/>
<DataGridTemplateColumn Header="操作">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Name="Edit" Content="修改" Click="Edit_Click" />
<Button Name="Delete" Content="删除" Click="Delete_Click" />
<Button Name="Route" Content="路由事件" Background="YellowGreen" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
MainWindow.xaml.cs中添加RouteClicked方法。
private void RouteClicked(object sender, RoutedEventArgs e) {
if ("Route".Equals((e.OriginalSource as FrameworkElement).Name)) {
Student stu = (Student) this.listStudent.SelectedItem;
MessageBox.Show("这是一个路由事件:" + stu.ToString());
}
}
效果如下:
九、添加第三方控件库
以上页面已近实现了对学生数据的增删改查操作。但是页面看起来不是特别美观。
下面将引入第三方控件库(HandyControl)来优化我们的代码。
HandyControl:GitHub - HandyOrg/HandyControl: Contains some simple and commonly used WPF controls
开始使用:
在Visual Studio上 工具栏上选择
工具 -> NuGet 包管理器 ->管理解决方案的NuGet程序包。
在浏览选项搜索HandyControl并下载安装。
在App.xaml中添加以下代码:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml"/>
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
添加命名空间:
xmlns:hc="https://handyorg.github.io/handycontrol"
至此配置完成。效果如下图:
源代码如下: