使用Visual Studio开发工具,我们可以编写在Windows系统上运行的桌面应用程序。其中,WPF(Windows Presentation Foundation)项目是一种常见的选择。然而,对于初学者来说,WPF项目中xaml页面的布局设计可能是一个难点。下面,将简要介绍WPF项目中xaml页面的数据绑定基础知识。
文章目录
- 页面布局
- 控件属性
- 更新内容
- 显示隐藏
- 更新样式
- 其它属性
- 绑定数据模型
- 数据绑定
- 结构体对象
- 绑定对象属性
- 内容显示
- 未初始化显示
- 设置对象属性
- 更新处理
- 绑定其它属性
- 数据列表
- 绑定数据调试
如果还不知道怎么创建WPF项目, 可以看以下文章,回顾一下再来
- Windows系统桌面应用程序编程开发新手入门-打造自己的小工具
- 桌面程序开发之xaml页面基础布局方式详解
- 桌面程序开发之xaml页面主题和样式详解
页面布局
带后缀名xaml的是页面的布局文件,打开内容大致如下
<Window x:Class="WpfApp4.MainWindow"
...
xmlns:local="clr-namespace:WpfApp4"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<!-- 这里设置统一控件的样式和加载资源 -->
</Window.Resources>
<Grid>
<!-- 这里开始添加控件布局 -->
<StackPanel>
<TextBlock x:Name="textBlock1" Text="Hello World" FontSize="24" />
<Button Click="Button_Click">点击按钮</Button>
</StackPanel>
</Grid>
</Window>
其中
xmlns:local="clr-namespace:WpfApp4"
是指定可用控件local
的命令空间
设计器下显示, 如下图
控件属性
在绑定控件的属性数据之前,需要了解如何改变控件的一些属性,
这些属性除了绑定,都是可通过写代码来改变的,以更新控件的显示内容和状态
更新内容
例如更新控件的文本内容,用一个文本控件TextBlock
,
这个控件里有个显示内容的属性Text
,在布局中内容修改如下
<TextBlock x:Name="textBlock1" Text="zs1028" FontSize="24" />
通过点击按钮控件来执行,在按钮事件Button_Click
中的代码添加内容,代码如下
textBlock1.Text = "Hello, zs1028";
点击运行后,效果如下图
显示隐藏
所有会显示的控件都有个可隐藏的属性,通过代码设置其属性Visibility
来改变即可,
通常用如下三个值:
- Visible 显示
- Hidden 隐藏,仍占用空间
- Collapsed 隐藏,不占空间
在布局中添加一个图像控件,内容如下
<Image x:Name="image1" Source="/zs1028的头像.jpg" Width="130" Stretch="Uniform" />
看设计器是否显示图片,如果填入的图片地址不对,就不会显示,
图片文件应放在项目根目录下资源文件夹Resources
中
要想把一个图片控件隐藏起来,
就在该控件标签里添加一个属性Visibility
,内容如下
<Image x:Name="image1" ... Visibility="Hidden" />
看设计器显示结果,就会发现图片不显示
或者,通过写代码,点击按钮隐藏该控件,代码如下
image1.Visibility = Visibility.Hidden;
上面的操作代码来看,虽然是把隐藏了,但是会占空间
点击运行后,效果如下图
如果要改变图片显示,修改代码如下
image1.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/520.jpg"));
文件地址对象类
Uri
传入的参数如果是项目根目录下需要带上前缀pack://application:,,,/
点击运行后,效果如下图
从上面看出,一些控件的属性数据类型不全是字符串String
类型,在代码中改变控件属性时要注意区别处理,
更新样式
例如,想要改变一个容器控件的背景,
就在布局中给其属性Background
设置为深蓝色背景,内容如下
<StackPanel x:Name="stackPanel1" Background="DarkBlue" />
...
</StackPanel>
其属性值是颜色名称,也可以改成 #1028CA 之类的十六进制颜色
可以通过写代码来改变,C#代码如下
stackPanel1.Background = Brushes.DarkBlue;
该属性的值在代码中不是字符串类型,而是在
Brushes
中预定义的SolidColorBrush
对象,它继承与Brush
类
如果在代码中要使用字符串类型的颜色值,需要转换处理,C#代码如下
string bgColorHtml = "#1028CA";
stackPanel1.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString(bgColorHtml));
点击运行后,效果如下图
其它属性
控件还有一些其它属性,用法同上面类似,在这里就不多讲,用到时候,自己研究。
慢慢就会发现,通过一行一行代码来改很多控件的属性,是很低效的,
想要提升工作效率,试试用控件的绑定数据
绑定数据模型
前端请求后台服务返回的数据,叫作数据模型,按实际需求来处理展示,
把这个数据处理为对象,与在后端写得数据库表存取的一条条数据都对应,
学过web前端页面数据绑定的同学应该很熟悉,
数据绑定
绑定的数据,就是当修改控件属性绑定的数据,控件会自动更新显示内容和状态,
与之前通过代码改变控件属性相比,这处理操作起来更容易一些
结构体对象
页面上有很多控件,控件的属性都能用一个结构体对象的属性来绑定,
先写一个自定义结构体对象类来当作数据模型,代码如下
public class DataModel
{
public string key1 { get; set; }
public DataModel()
{
}
}
写得不多的话,就写在页面的代码里,这样方便点
页面代码里有一个构造方法MainWindow()
,
在这里面写,将DataContext
初始化,代码如下,
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// 用自定义对象的属性数据
this.DataContext = new DataModel();
}
}
这窗体对象有个属性
DataContext
,是页面的数据上下文,
为其赋值为DataModel
类的实例,使用控件就可以绑定实例的属性
绑定对象属性
实例对象类DataModel
中有定义了一个属性key1
,可以从页面数据上下文中获取,
在页面布局中,绑定这个属性,改后内容如下
<TextBlock Text="{Binding key1}" FontSize="14" Foreground="Blue" />
其文本控件的属性值
Text
使用花括号将内容包括起来,
其开头写了Binding
,表示绑定一个变量,指向属性名key1
在设计器上,这个文本控件默认是不显示内容的,
内容显示
要想显示内容,需要在绑定的属性Text
中添加一段FallbackValue
,改后内容如下
<TextBlock Text="{Binding key1, FallbackValue='zs1028'}" ... />
点击运行后,会发现文件控件显示了内容,如下图
这是因为变量属性
key1
没有初始化赋值,
未初始化显示
要在绑定的属性未初始化时提示的话,可以再添加一段TargetNullValue
,改后内容如下
<TextBlock Text="{Binding key1, FallbackValue='zs1028', TargetNullValue='未初始化赋值'}" .../>
点击运行后,会发现文件控件显示未初始化赋值
内容,
设置对象属性
接下来,通过按钮点击给其key1
赋值,代码如下
DataModel data = (DataModel)this.DataContext;
data.key1 = "hello zs1028";
那页面就会自动更新相关的控件显示状态,对吗,
点击运行后发现,和预期的不一致,点击按钮后文本控件没有自动更新,
更新处理
问题出在这里,自定义对象DataModel
类没有继承INotifyPropertyChanged
接口,
继承这个接口,实现通知更新的处理,
修改后,代码如下
public class DataModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public string key1
{
get { return _key1; }
set
{
_key1 = value;
OnPropertyChanged(nameof(key1));
}
}
private string _key1 { get; set; }
public DataModel()
{
}
}
当运行时,修改其中的属性
key1
后,它会调用一个方法OnPropertyChanged()
通知属性改变,
那页面上就会自动更新相关的控件显示状态,
点击运行后,效果如下图
绑定其它属性
除了绑定数据类型有字符串的属性,还有其它属性,
用法参考之前代码设置控件属性一样,中间需要转换,
在这里就不多讲,用到时候,自己研究。
数据列表
如果用到展示列表之类的控件,这些列表控件有ItemsControl
和ListBox
,
这些列表控件使用的数据属性是ItemsSource
,是一个列表或数组,数据集合类型,
想到列表
List
类,用它来代替使用就会有问题,因为这个类没有继承类似更新项属性的接口和实现
这里使用数据集合ObservableCollection
对象,作为列表,
这个对象类继承了Collection
, INotifyCollectionChanged
, INotifyPropertyChanged
,所以在修改数据项时会自动更新,
使用前需要添加来自
System.Collections.ObjectModel
的引用,
在之前的自定义对象中添加一个属性keys1
,为数据列表, 代码如下
public class DataModel : INotifyPropertyChanged
{
/.../
public ObservableCollection<KeyValuePair<string, string>> keys1
{
get { return _keys1; }
set
{
_keys1 = value;
OnPropertyChanged(nameof(keys1));
}
}
private ObservableCollection<KeyValuePair<string, string>> _keys1 { set; get; }
public DataModel()
{
}
}
在页面布局中,应改成这样,
设置列表控件的属性ItemsSource
指向数据集合变量,内容如下
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DockPanel>
<Label DockPanel.Dock="Left" FontWeight="Bold" Content="{Binding YourName}" />
<TextBlock Padding="0,5" Text="{Binding YourCode}" />
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
在标签
DataTemplate
对内填入的内容是列表项的布局,其绑定的数据上下文是指向该列表控件本身的当时列表项数据ListItem
对象
列表项数据ListItem
是一个自定义对象类,写出来,代码如下
public class ListItem
{
public string YourName { get; set; }
public string YourCode { get; set; }
public ListItem(string name, string code)
{
YourName = name;
YourCode = code;
}
}
现在点击运行是看不到列表的,还没有列表数据,
直接在自定义对象的构造方法中添加列表数据,代码如下
public DataModel()
{
_keys1 = new ObservableCollection<ListItem>
{
new ListItem("你的名字","你的代号"),
new ListItem("zs1028","1028"),
};
}
点击运行后,效果如下图
在点击按钮事件中,实现添加新项,代码如下
DataModel data = (DataModel)this.DataContext;
//...
data.keys1.Add(new ListItem(DateTime.Now.ToString("孙悟空 HHmmss"), data.keys1.Count.ToString("D4")));
点击运行后,效果如下图
绑定数据调试
点击运行时,程序窗口标题栏上会出现一个开发者工具悬浮窗,
如下图,标为橙色的图标按钮就是调试查看绑定情况的,
上面都是基本上能用到的,对需要学习的新手来说很有帮助,就讲到这里,
更多绑定数据详情,参考微软官方的文档
将 WPF 控件绑定到 .NET Framework 应用程序中的数据