Day 3 - 常用控件
建议用时:210-240 分钟
你将学会什么
- 知道
TextBlock、TextBox、Button、CheckBox、ComboBox、ListBox分别负责什么。 - 会写控件最常用的属性:
Text、Content、PlaceholderText、IsChecked、SelectedIndex、Click。 - 会用
x:Name给控件命名,让 C# 代码能找到它。 - 会写一个按钮点击事件,从输入框、复选框、下拉框里读取值。
- 会把读取到的数据显示到界面上,而不是只让按钮摆在那里。
本页先用 code-behind 写点击事件,也就是在 MainWindow.axaml.cs 里处理按钮点击。这样最直接,能看清“界面控件”和“C# 代码”是怎么连接的。后面再学习 MVVM 和命令绑定。
本页固定顺序
- 先学第一部分:弄懂今天最小、最重要的知识,并运行短例子。
- 再学第二部分:把刚学的知识组合成一个完整例子。
- 然后做第三部分:自己跟着敲,再完成重复训练和每日小测。
- 最后做第四部分:先独立完成作业,再用完整答案检查。
学习衔接
上一页学习的是“XAML 布局”,今天继续学习“常用控件”。先使用上一页已经会的写法,再只增加今天这个新知识点;如果前置内容还不能独立敲出,先回上一页复习,不要硬跳。
今天的最低通过线
第一次学习不要求背完整页。完成下面 3 项,就可以继续:
- 能用自己的话说明“常用控件”解决什么问题。
- 把第一部分的短例子亲手敲完,并确认每个例子都能运行。
- 不看完整答案完成第三部分至少前 3 个例子,再主动改一个值观察结果。
第一部分:先学原理和最小知识
这一部分从最小知识开始。先读解释,再把紧跟着的短例子敲一遍。今天不追求控件数量多,而是把“显示、输入、点击、选择、反馈”这一条链路搞清楚。
1. 控件是什么
控件就是窗口上能看见或能操作的界面元素。
| 控件 | 作用 | 常见位置 |
|---|---|---|
TextBlock | 显示只读文字 | 标题、标签、提示 |
TextBox | 输入或显示一段文本 | 名称、价格、备注 |
Button | 触发一个动作 | 保存、删除、查询 |
CheckBox | 表示是或否 | 是否启用、是否默认 |
ComboBox | 从多个选项里选一个 | 分类、状态、类型 |
ListBox | 显示一组条目 | 商品列表、菜单、日志 |
先按“用户要看什么、输入什么、点击什么、选择什么”来选控件。
2. TextBlock 和 TextBox 不一样
TextBlock 用来显示文字,用户一般不能直接改。
<TextBlock Text="商品名称" />TextBox 用来输入文字,用户可以点进去打字。
<TextBox Text="Keyboard" />不要用 TextBox 充当普通说明文字。说明文字用 TextBlock,输入内容才用 TextBox。
3. Content 和 Text 的区别
Avalonia 控件常见两个属性:Text 和 Content。
| 属性 | 常见控件 | 含义 |
|---|---|---|
Text | TextBlock、TextBox | 文字内容 |
Content | Button、CheckBox、ListBoxItem、ComboBoxItem | 控件里面显示的内容 |
例子:
<TextBlock Text="商品名称" />
<Button Content="保存" />按钮用 Content,因为按钮里面将来不一定只能放文字,也可以放更复杂的内容。
4. PlaceholderText 是输入提示,不是真正输入值
<TextBox PlaceholderText="请输入商品名称" />PlaceholderText 只是输入框为空时显示的提示。用户没有输入时,TextBox.Text 不会自动变成 请输入商品名称。
如果要给输入框一个真实默认值,要写:
<TextBox Text="Keyboard" />5. x:Name 的作用
如果 C# 代码要读取某个控件,就要先让这个控件有名字。
<TextBox x:Name="NameBox" />有了这个名字,MainWindow.axaml.cs 里就能写:
string name = NameBox.Text ?? "";名字要清楚,推荐用“含义 + 控件类型”的方式:
| 控件用途 | 推荐名字 |
|---|---|
| 商品名称输入框 | NameBox |
| 分类下拉框 | CategoryBox |
| 是否启用复选框 | EnabledBox |
| 结果文字 | ResultText |
6. Button 的 Click 事件
按钮本身只是一个控件。它不会自动保存数据。要让按钮做事,需要把点击事件连接到 C# 方法。
XAML 里写:
<Button Content="保存"
Click="OnSaveClick" />C# 里写:
private void OnSaveClick(object? sender, RoutedEventArgs e)
{
ResultText.Text = "已经点击保存。";
}Click="OnSaveClick" 的意思是:用户点击按钮时,执行名叫 OnSaveClick 的方法。
7. 事件方法的两个参数是什么
private void OnSaveClick(object? sender, RoutedEventArgs e)先理解到这个程度就够:
| 参数 | 含义 |
|---|---|
sender | 触发事件的那个控件,一般就是按钮 |
e | 事件附带的信息 |
普通按钮点击里经常用不到这两个参数,但方法签名要写对,否则 XAML 找不到对应方法。
8. CheckBox.IsChecked 为什么要写 == true
CheckBox.IsChecked 的类型不是普通 bool,它可以是:
true:选中。false:没选中。null:不确定状态。
所以常见写法是:
bool enabled = EnabledBox.IsChecked == true;这句话的意思是:只有明确等于 true,才当成启用。
9. ComboBox.SelectedItem 读出来是什么
如果你的下拉框里写的是 ComboBoxItem:
<ComboBox x:Name="CategoryBox">
<ComboBoxItem Content="普通商品" />
<ComboBoxItem Content="虚拟商品" />
</ComboBox>那么 C# 里读 SelectedItem 时,拿到的是被选中的 ComboBoxItem。
string category = CategoryBox.SelectedItem is ComboBoxItem item
? item.Content?.ToString() ?? "未选择分类"
: "未选择分类";这段代码做了两件事:
- 确认选中的东西确实是
ComboBoxItem。 - 从
item.Content里取出真正显示的文字。
10. 控件值读取顺序
写点击事件时,不要一上来就写很多逻辑。按这个顺序:
- 先读取输入框。
- 再读取复选框。
- 再读取下拉框。
- 再拼出一段结果文字。
- 最后把结果显示到
TextBlock。
也就是:输入控件 -> C# 方法 -> 输出控件。
Avalonia 常用控件属性速查
| 控件 | 常用属性 | 作用 |
|---|---|---|
TextBlock | Text | 显示文字 |
TextBox | Text、PlaceholderText | 输入文本和提示 |
Button | Content、Click、Command | 按钮文字和操作 |
CheckBox | IsChecked、Content | 勾选状态 |
ComboBox | ItemsSource、SelectedItem | 下拉选择 |
ListBox | ItemsSource、SelectedItem | 列表和选中项 |
Border | Padding、Margin、BorderThickness | 包裹内容 |
DatePicker | SelectedDate | 日期选择 |
输入框最常用写法:
<TextBox
Text="{Binding ProductName, Mode=TwoWay}"
PlaceholderText="请输入商品名称" />按钮最常用写法:
<Button
Content="保存"
Command="{Binding SaveCommand}" />第二部分:把知识组合成完整例子
今天要做的是一个“商品录入小窗口”。窗口里有输入框、复选框、下拉框、列表和按钮。点击按钮后,C# 代码会读取控件上的值,再把结果显示到页面底部。
MainWindow.axaml
把下面内容放到 Views/MainWindow.axaml。
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ProductApp.Views.MainWindow"
Width="640"
Height="460"
Title="常用控件练习">
<Grid RowDefinitions="Auto,Auto,Auto,*"
RowSpacing="12"
Margin="20">
<TextBlock Grid.Row="0"
Text="商品录入"
FontSize="24"
FontWeight="Bold" />
<Grid Grid.Row="1"
RowDefinitions="Auto,Auto,Auto"
ColumnDefinitions="Auto,*"
RowSpacing="10"
ColumnSpacing="12">
<TextBlock Grid.Row="0"
Grid.Column="0"
Text="名称"
VerticalAlignment="Center" />
<TextBox x:Name="NameBox"
Grid.Row="0"
Grid.Column="1"
PlaceholderText="请输入商品名称"
Text="Keyboard" />
<TextBlock Grid.Row="1"
Grid.Column="0"
Text="分类"
VerticalAlignment="Center" />
<ComboBox x:Name="CategoryBox"
Grid.Row="1"
Grid.Column="1"
SelectedIndex="0">
<ComboBoxItem Content="普通商品" />
<ComboBoxItem Content="虚拟商品" />
<ComboBoxItem Content="服务商品" />
</ComboBox>
<TextBlock Grid.Row="2"
Grid.Column="0"
Text="状态"
VerticalAlignment="Center" />
<CheckBox x:Name="EnabledBox"
Grid.Row="2"
Grid.Column="1"
Content="启用这个商品"
IsChecked="True" />
</Grid>
<StackPanel Grid.Row="2"
Orientation="Horizontal"
Spacing="8">
<Button Content="保存"
Click="OnSaveClick" />
<Button Content="清空结果"
Click="OnClearClick" />
</StackPanel>
<Border Grid.Row="3"
BorderBrush="#DDDDDD"
BorderThickness="1"
Padding="12">
<StackPanel Spacing="8">
<TextBlock Text="当前商品列表"
FontWeight="Bold" />
<ListBox>
<ListBoxItem Content="Keyboard" />
<ListBoxItem Content="Mouse" />
<ListBoxItem Content="Monitor" />
</ListBox>
<TextBlock x:Name="ResultText"
Text="点击保存后,这里会显示读取到的数据。" />
</StackPanel>
</Border>
</Grid>
</Window>MainWindow.axaml.cs
把下面内容放到 Views/MainWindow.axaml.cs。
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace ProductApp.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnSaveClick(object? sender, RoutedEventArgs e)
{
string name = NameBox.Text ?? "";
bool enabled = EnabledBox.IsChecked == true;
string category = CategoryBox.SelectedItem is ComboBoxItem item
? item.Content?.ToString() ?? "未选择分类"
: "未选择分类";
ResultText.Text = $"名称:{name};分类:{category};启用:{enabled}";
}
private void OnClearClick(object? sender, RoutedEventArgs e)
{
ResultText.Text = "结果已清空。";
}
}先用一句话理解
XAML 负责把控件画出来;x:Name 给控件起名字;Click="OnSaveClick" 把按钮和 C# 方法连接起来;C# 方法读取控件值并修改 ResultText.Text。
第三部分:跟着敲代码
从这里开始动手。每个例子都说明要改哪个文件。先运行窗口,再改下一段。
例子 1:只显示控件,不写事件
先练控件本身。把下面内容放到 Views/MainWindow.axaml。
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ProductApp.Views.MainWindow"
Width="460"
Height="360"
Title="控件显示">
<StackPanel Margin="20"
Spacing="10">
<TextBlock Text="商品名称"
FontSize="18"
FontWeight="Bold" />
<TextBox PlaceholderText="请输入商品名称" />
<CheckBox Content="启用这个商品"
IsChecked="True" />
<ComboBox SelectedIndex="0">
<ComboBoxItem Content="普通商品" />
<ComboBoxItem Content="虚拟商品" />
<ComboBoxItem Content="服务商品" />
</ComboBox>
<Button Content="保存" />
<ListBox>
<ListBoxItem Content="Keyboard" />
<ListBoxItem Content="Mouse" />
<ListBoxItem Content="Monitor" />
</ListBox>
</StackPanel>
</Window>运行后先确认:
- 能看到输入框。
- 能勾选和取消勾选复选框。
- 能展开下拉框。
- 能看到列表。
- 按钮能被点击,但现在不会执行保存逻辑。
例子 2:按钮点击后修改文字
这个例子先不读取输入,只练“按钮 -> C# 方法 -> 修改界面文字”。
MainWindow.axaml
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ProductApp.Views.MainWindow"
Width="420"
Height="240"
Title="按钮点击">
<StackPanel Margin="20"
Spacing="12">
<Button Content="点我"
Click="OnButtonClick" />
<TextBlock x:Name="MessageText"
Text="按钮还没有被点击。" />
</StackPanel>
</Window>MainWindow.axaml.cs
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace ProductApp.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnButtonClick(object? sender, RoutedEventArgs e)
{
MessageText.Text = "按钮已经被点击。";
}
}这一步只看一件事:Click="OnButtonClick" 和 C# 里的 OnButtonClick 名字必须完全一致。
例子 3:点击按钮读取 TextBox
这个例子开始读取输入框里的文字。
MainWindow.axaml
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ProductApp.Views.MainWindow"
Width="460"
Height="260"
Title="读取 TextBox">
<StackPanel Margin="20"
Spacing="10">
<TextBlock Text="商品名称" />
<TextBox x:Name="NameBox"
PlaceholderText="请输入商品名称" />
<Button Content="显示名称"
Click="OnShowNameClick" />
<TextBlock x:Name="ResultText"
Text="这里会显示输入结果。" />
</StackPanel>
</Window>MainWindow.axaml.cs
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace ProductApp.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnShowNameClick(object? sender, RoutedEventArgs e)
{
string name = NameBox.Text ?? "";
ResultText.Text = $"你输入的商品名称是:{name}";
}
}如果输入框是空的,NameBox.Text 可能是 null。?? "" 的意思是:如果没有文字,就当成空字符串处理。
例子 4:读取 CheckBox 的选中状态
MainWindow.axaml
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ProductApp.Views.MainWindow"
Width="460"
Height="240"
Title="读取 CheckBox">
<StackPanel Margin="20"
Spacing="12">
<CheckBox x:Name="EnabledBox"
Content="启用这个商品"
IsChecked="True" />
<Button Content="读取状态"
Click="OnReadEnabledClick" />
<TextBlock x:Name="ResultText"
Text="这里会显示启用状态。" />
</StackPanel>
</Window>MainWindow.axaml.cs
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace ProductApp.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnReadEnabledClick(object? sender, RoutedEventArgs e)
{
bool enabled = EnabledBox.IsChecked == true;
ResultText.Text = enabled ? "当前状态:启用" : "当前状态:停用";
}
}这里不要直接写 bool enabled = EnabledBox.IsChecked;,因为 IsChecked 不是普通 bool。
例子 5:读取 ComboBox 的选中项
MainWindow.axaml
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ProductApp.Views.MainWindow"
Width="480"
Height="260"
Title="读取 ComboBox">
<StackPanel Margin="20"
Spacing="12">
<TextBlock Text="商品分类" />
<ComboBox x:Name="CategoryBox"
SelectedIndex="0">
<ComboBoxItem Content="普通商品" />
<ComboBoxItem Content="虚拟商品" />
<ComboBoxItem Content="服务商品" />
</ComboBox>
<Button Content="读取分类"
Click="OnReadCategoryClick" />
<TextBlock x:Name="ResultText"
Text="这里会显示选中的分类。" />
</StackPanel>
</Window>MainWindow.axaml.cs
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace ProductApp.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnReadCategoryClick(object? sender, RoutedEventArgs e)
{
string category = CategoryBox.SelectedItem is ComboBoxItem item
? item.Content?.ToString() ?? "未选择分类"
: "未选择分类";
ResultText.Text = $"当前分类:{category}";
}
}这段写法看起来长,但它解决了两个问题:没有选中时不会报错,选中后能拿到真正显示的文字。
例子 6:组合成一个商品录入表单
这个例子把前面的控件组合到一个表单里。
MainWindow.axaml
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ProductApp.Views.MainWindow"
Width="620"
Height="420"
Title="商品录入">
<Grid RowDefinitions="Auto,Auto,*"
RowSpacing="12"
Margin="20">
<TextBlock Grid.Row="0"
Text="商品录入"
FontSize="24"
FontWeight="Bold" />
<Grid Grid.Row="1"
RowDefinitions="Auto,Auto,Auto,Auto"
ColumnDefinitions="Auto,*"
RowSpacing="10"
ColumnSpacing="12">
<TextBlock Grid.Row="0"
Grid.Column="0"
Text="名称"
VerticalAlignment="Center" />
<TextBox x:Name="NameBox"
Grid.Row="0"
Grid.Column="1"
PlaceholderText="请输入商品名称" />
<TextBlock Grid.Row="1"
Grid.Column="0"
Text="分类"
VerticalAlignment="Center" />
<ComboBox x:Name="CategoryBox"
Grid.Row="1"
Grid.Column="1"
SelectedIndex="0">
<ComboBoxItem Content="普通商品" />
<ComboBoxItem Content="虚拟商品" />
<ComboBoxItem Content="服务商品" />
</ComboBox>
<TextBlock Grid.Row="2"
Grid.Column="0"
Text="状态"
VerticalAlignment="Center" />
<CheckBox x:Name="EnabledBox"
Grid.Row="2"
Grid.Column="1"
Content="启用商品"
IsChecked="True" />
<Button Grid.Row="3"
Grid.Column="1"
Content="保存"
HorizontalAlignment="Right"
Click="OnSaveClick" />
</Grid>
<TextBlock x:Name="ResultText"
Grid.Row="2"
Text="保存结果会显示在这里。" />
</Grid>
</Window>MainWindow.axaml.cs
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace ProductApp.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnSaveClick(object? sender, RoutedEventArgs e)
{
string name = NameBox.Text ?? "";
bool enabled = EnabledBox.IsChecked == true;
string category = CategoryBox.SelectedItem is ComboBoxItem item
? item.Content?.ToString() ?? "未选择分类"
: "未选择分类";
ResultText.Text = $"保存成功:{name},{category},启用状态:{enabled}";
}
}常见错误和修法
| 错误 | 为什么错 | 修法 |
|---|---|---|
| 控件名字没写 | code-behind 找不到控件 | 需要在 C# 访问时加 x:Name |
TextBox.Text 可能为空 | 输入框内容不一定有值 | 读取后先做空白判断 |
ComboBox 没有默认选项 | 保存时可能没有选中值 | 设置 SelectedIndex 或处理空值 |
| 按钮点击事件名写错 | XAML 找不到处理方法 | XAML 和 .axaml.cs 方法名保持一致 |
| 错误提示没有固定位置 | 用户不知道哪里出错 | 页面保留 ErrorText 或 MessageText |
小白重复敲写训练
控件不要一次放满窗口,每段只练三种。
训练 1:文本输入和按钮
<StackPanel Margin="20" Spacing="8">
<TextBox Name="NameInput" Watermark="请输入名称" />
<Button Content="读取名称" Click="ReadName_Click" />
<TextBlock Name="ResultText" />
</StackPanel>private void ReadName_Click(object? sender, RoutedEventArgs e)
{
ResultText.Text = NameInput.Text;
}训练 2:复选框
<CheckBox Name="EnabledCheck" Content="启用商品" />
<Button Content="检查" Click="Check_Click" />private void Check_Click(object? sender, RoutedEventArgs e)
{
ResultText.Text = EnabledCheck.IsChecked == true ? "已启用" : "未启用";
}训练 3:下拉选择
<ComboBox Name="CategoryBox" SelectedIndex="0">
<ComboBoxItem Content="电脑" />
<ComboBoxItem Content="配件" />
<ComboBoxItem Content="办公" />
</ComboBox>第三遍增加一个分类,并尝试读取当前选择。
每日小测
做完本页后,用这 5 题检查是否真的掌握。
1. 判断题
本页的目标不是只把代码运行起来,还要能说清楚“为什么这样写”。
答案:对。能运行只是第一步,能解释原理、常用操作和常见错误,才说明本页内容进入了可复用能力。
2. 填空题
本页主题是:常用控件。今天至少要掌握的 3 个点是:
1. 知道 `TextBlock`、`TextBox`、`Button`、`CheckBox`、`ComboBox`、`ListBox` 分别负责什么。
2. 会写控件最常用的属性:`Text`、`Content`、`PlaceholderText`、`IsChecked`、`SelectedIndex`、`Click`。
3. 会用 `x:Name` 给控件命名,让 C# 代码能找到它。答案:以上 3 点必须能用自己的代码跑通,不能只停留在阅读。
3. 流程题
遇到本页相关功能时,先按什么顺序处理?
答案:先看完整例子,确认最终效果;再读原理和名词;然后跟着第三部分从空项目敲代码;最后对照作业答案检查。
4. 找错误题
如果本页代码运行失败,第一步应该做什么?
答案:先看终端或 IDE 里的第一条错误,找到文件名和行号;不要同时改很多地方。再回到本页的“常见错误和修法”表格,对照错误类型逐项排查。
5. 改需求题
在本页完整例子跑通后,至少改一个小需求。
可选改法:
- 改一个字段名称。
- 多加一个校验条件。
- 多输出一行结果。
- 把固定数据改成用户输入。
- 把一次处理改成多条数据处理。
答案标准:修改后能重新运行,并能说明这次修改影响了哪一段逻辑。重点检查:知道 TextBlock、TextBox、Button、CheckBox、ComboBox、ListBox 分别负责什么。。
上位机专项练习
TextBox、ComboBox、Button、CheckBox 和 DataGrid 是配置与监控界面的常用控件。
下面 3 个例子都要亲手敲。先运行原代码,再完成每个例子后面的改动任务。
专项例子 1:填写设备连接参数
<StackPanel Margin="20" Spacing="10">
<TextBox Watermark="设备名称" Text="PLC-01" />
<ComboBox SelectedIndex="0">
<ComboBoxItem Content="Modbus TCP" />
<ComboBoxItem Content="Modbus RTU" />
</ComboBox>
<CheckBox Content="启动时自动连接" />
<Button Content="保存配置" />
</StackPanel>运行结果或界面效果:
可以输入名称、选择协议和保存改动任务: 增加 IP 地址输入框。
专项例子 2:显示实时数值
<StackPanel Margin="20">
<TextBlock Text="当前温度" />
<TextBlock Text="26.8 C" FontSize="36" FontWeight="Bold" />
<ProgressBar Minimum="0" Maximum="100" Value="26.8" />
</StackPanel>运行结果或界面效果:
文字和进度条同时显示温度改动任务: 把最大值改成 80。
专项例子 3:显示设备表格
<DataGrid AutoGenerateColumns="False" Height="220">
<DataGrid.Columns>
<DataGridTextColumn Header="设备" Binding="{Binding Name}" />
<DataGridTextColumn Header="状态" Binding="{Binding Status}" />
<DataGridTextColumn Header="温度" Binding="{Binding Temperature}" />
</DataGrid.Columns>
</DataGrid>运行结果或界面效果:
表格包含设备、状态、温度三列改动任务: 增加“更新时间”列。
第四部分:作业完整答案
这一部分给出当天作业的完整答案。先照第三部分敲一遍,再用这里检查结果。
作业要求
做一个静态商品录入窗口,并且按钮点击后能读取控件值。
页面必须包含:
TextBox:输入商品名称。ComboBox:选择商品分类。CheckBox:选择是否启用。ListBox:显示已有商品。Button:点击后读取上面三个输入控件。TextBlock:显示保存结果。
拆解步骤
- 先在
MainWindow.axaml里把控件摆出来。 - 给 C# 代码要读取的控件加
x:Name。 - 给按钮加
Click="OnSaveClick"。 - 在
MainWindow.axaml.cs里写OnSaveClick方法。 - 在方法里读取
NameBox.Text。 - 在方法里读取
EnabledBox.IsChecked == true。 - 在方法里读取
CategoryBox.SelectedItem。 - 最后把结果写到
ResultText.Text。
MainWindow.axaml 完整答案
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ProductApp.Views.MainWindow"
Width="640"
Height="460"
Title="常用控件练习">
<Grid RowDefinitions="Auto,Auto,Auto,*"
RowSpacing="12"
Margin="20">
<TextBlock Grid.Row="0"
Text="商品录入"
FontSize="24"
FontWeight="Bold" />
<Grid Grid.Row="1"
RowDefinitions="Auto,Auto,Auto"
ColumnDefinitions="Auto,*"
RowSpacing="10"
ColumnSpacing="12">
<TextBlock Grid.Row="0"
Grid.Column="0"
Text="名称"
VerticalAlignment="Center" />
<TextBox x:Name="NameBox"
Grid.Row="0"
Grid.Column="1"
PlaceholderText="请输入商品名称"
Text="Keyboard" />
<TextBlock Grid.Row="1"
Grid.Column="0"
Text="分类"
VerticalAlignment="Center" />
<ComboBox x:Name="CategoryBox"
Grid.Row="1"
Grid.Column="1"
SelectedIndex="0">
<ComboBoxItem Content="普通商品" />
<ComboBoxItem Content="虚拟商品" />
<ComboBoxItem Content="服务商品" />
</ComboBox>
<TextBlock Grid.Row="2"
Grid.Column="0"
Text="状态"
VerticalAlignment="Center" />
<CheckBox x:Name="EnabledBox"
Grid.Row="2"
Grid.Column="1"
Content="启用这个商品"
IsChecked="True" />
</Grid>
<StackPanel Grid.Row="2"
Orientation="Horizontal"
Spacing="8">
<Button Content="保存"
Click="OnSaveClick" />
<Button Content="清空结果"
Click="OnClearClick" />
</StackPanel>
<Border Grid.Row="3"
BorderBrush="#DDDDDD"
BorderThickness="1"
Padding="12">
<StackPanel Spacing="8">
<TextBlock Text="当前商品列表"
FontWeight="Bold" />
<ListBox>
<ListBoxItem Content="Keyboard" />
<ListBoxItem Content="Mouse" />
<ListBoxItem Content="Monitor" />
</ListBox>
<TextBlock x:Name="ResultText"
Text="点击保存后,这里会显示读取到的数据。" />
</StackPanel>
</Border>
</Grid>
</Window>MainWindow.axaml.cs 完整答案
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace ProductApp.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnSaveClick(object? sender, RoutedEventArgs e)
{
string name = NameBox.Text ?? "";
bool enabled = EnabledBox.IsChecked == true;
string category = CategoryBox.SelectedItem is ComboBoxItem item
? item.Content?.ToString() ?? "未选择分类"
: "未选择分类";
ResultText.Text = $"名称:{name};分类:{category};启用:{enabled}";
}
private void OnClearClick(object? sender, RoutedEventArgs e)
{
ResultText.Text = "结果已清空。";
}
}运行后应该看到什么
- 页面顶部显示
商品录入。 - 输入框里默认有
Keyboard。 - 分类下拉框默认选中
普通商品。 - 复选框默认是选中状态。
- 点击
保存后,底部文字显示名称、分类和启用状态。 - 点击
清空结果后,底部文字变成结果已清空。。
如果报错,按这个顺序检查
- 如果提示找不到
OnSaveClick,检查 XAML 里的Click名字和 C# 方法名是否完全一致。 - 如果提示找不到
NameBox,检查TextBox是否写了x:Name="NameBox"。 - 如果提示找不到
RoutedEventArgs,检查.axaml.cs顶部是否有using Avalonia.Interactivity;。 - 如果点击按钮没有变化,检查
ResultText这个TextBlock是否写了x:Name="ResultText"。 - 如果分类显示
未选择分类,检查ComboBox是否有SelectedIndex="0"。
今天真正要掌握的闭环
界面交互可以先按这条线理解:
用户输入或选择
-> 用户点击按钮
-> Click 事件执行 C# 方法
-> C# 方法读取控件值
-> C# 方法把结果写回界面能把这条线走通,后面的绑定、命令、MVVM 才有落点。