创建交互式 UI
在前面几课中,你生成了一个提示用户输入用户名的简单窗体 UI;单击窗体中的按钮后,用户便会看到问候语。 在本课中,你会将此窗体更改为,在用户至少输入三个字符前禁用或隐藏“提交”按钮,从而提高一点此窗体的易用性。
首先来看一下通过数据绑定设置 MainPageLogic.UserName
值的确切时间。
1.放置断点
打开 MainPageLogic.cs
文件,并找到 UserName
属性所在的行。
public string UserName { get; set; }
对 Setter 设置断点,具体方法为将插入点移到 set
文本内并按 F9。 也可以通过右键单击“set
”,并选择“断点”/“插入断点”来实现。
2.在调试模式下运行应用
接下来,在调试模式下运行应用(按 F5 或选择“调试”/“开始调试”)。 在 TextBox
中键入一些内容,并注意不要命中断点。 如果按 Tab 键,它会将输入焦点移到下一个控件(在此示例中为按钮)。 TextBox
失去焦点会更新绑定,进而导致断点被命中。
3.将绑定更改为在用户每次击键时更新
停止调试(按 Shift+F5 或选择“调试”/“停止调试”)。
为了提供有关“提交”按钮启用时间的准确反馈,不能等到 TextBox
失去焦点。 幸运的是,可以更改绑定行为。 可以强制它在文本属性每次更改时都更新 UserName
属性(这是源,因为讨论的是 TwoWay
绑定)。 需要更改绑定的 UpdateSourceTrigger
,它默认设为 LostFocus
。 UpdateSourceTrigger
定义导致源更新的环境。
打开 MainPage.xaml,并找到 TextBox
。 然后,通过添加 UpdateSourceTrigger=PropertyChanged
来更改绑定。 整个 TextBox
标记现在应如下所示:
<TextBox Name="tbUserName"
Margin="10"
Width="150"
VerticalAlignment="Center"
Text="{x:Bind Logic.UserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
如果现在调试应用,可以看到每次击键和文本更改都会命中断点。 太棒了!
你可能还记得,使用 UI 到 UI 绑定来显示问候语时,每次击键都会触发绑定。 在这种情况下,绑定是对 TextBlock
定义,因此源是 TextBox.Text
属性,它确实会在用户每次击键时更改。 UpdateSourceTrigger
影响另一个方向的数据流。 它从绑定源流向定义了绑定的控件(绑定目标)。
5.添加 IsSubmitAllowed
属性
接下来,添加指明是否允许提交窗体的布尔属性。 打开 MainPageLogic.cs,并向 MainPageLogic
类添加新属性。
public bool IsSubmitAllowed => UserName?.Trim().Length > 2;
这是一个非常简单的验证,即如果用户输入的文本(剪裁掉前导和尾随空格字符)包含超过两个字符,就接受它作为用户名。
6. 在 UserName
每次更改后重新评估 IsSubmitAllowed
必须指示 UI 框架,何时重新评估此属性并在 UI 上反映它。 触发此重新评估的最佳方式是在 UserName
属性的 Setter 中调用 RaisePropertyChanged
。 必须先将 Setter 转换为完整属性,然后才能向 Setter 添加代码。 将 UserName
属性替换为以下代码:
private string _userName;
public string UserName
{
get { return _userName; }
set
{
_userName = value;
RaisePropertyChanged(nameof(IsSubmitAllowed));
}
}
我们没有对此属性使用 INotifyPropertyChanged
,因为还没有出现通过代码更改 UserName
属性的情况。 不过,每当 TextBox
中的文本更改时,必须指示 UI,IsSubmitAllowed
属性可能已更改并应重新接受评估。
7.将 IsSubmitAllowed
属性绑定到按钮的 IsEnabled
属性
至此,代码已完成。 返回到 MainPage.xaml,并找到“提交”按钮。 添加 IsEnabled
属性,这样按钮的 XAML 现在如下所示:
<Button Margin="10"
VerticalAlignment="Center"
Click="{x:Bind Logic.Submit}"
IsEnabled="{x:Bind Logic.IsSubmitAllowed, Mode=OneWay}">Submit</Button>
8.运行应用
如果现在运行应用,应该会看到“提交”按钮默认处于禁用状态。 如果你键入一些空格,它也仍继续处于禁用状态;只有在用户输入至少三个非空格字符时,此按钮才会启用。
虽然此示例执行的是某验证,但 UWP 有一组丰富的验证功能,后面的模块将介绍这些功能。
9.隐藏“提交”按钮
你或设计人员可能会决定更进一步,即在用户可以按“提交”按钮前隐藏它。 这是一种简单更改,所以让我们现在就进行吧。 只需编辑 XAML,并将 IsEnabled
更改为 Visibility
即可。
不过,如果键入几个字符,便会发现整个 UI 跳转。 这是因为周围的 StackPanel
是水平居中 (HorizontalAlignment="Center"
),且 StackPanel
的宽度在 Button
折叠时较小。 若要解决此问题,可以将 Button
放入 100 个单位宽度的 Border
中,如下所示。
<Border Width="100">
<Button Margin="10"
VerticalAlignment="Center"
Click="{x:Bind Logic.Submit}"
Visibility="{x:Bind Logic.IsSubmitAllowed, Mode=OneWay}">Submit</Button>
</Border>
这样,StackPanel
的宽度就不会在 Border
内的 Button
再次出现时变化。
总结
本课介绍了如何调试绑定。 你不仅了解了 UpdateSourceTrigger
绑定选项,还看到了更多的数据绑定示例。 此外,本课还举例介绍了如何在正确使用数据绑定的情况下,更改 UI 的外观和行为,而不影响 C# 代码。
下一课将探究如何使用数据绑定来显示列表中的多个项。
在前面几课中,你创建了一个提示用户输入用户名的简单窗体 UI;单击窗体中的按钮后,用户便会看到问候语。 在本课中,你会将此窗体更改为,在用户至少输入三个字符前禁用或隐藏“提交”按钮,从而提高一点此窗体的易用性。
首先来看一下通过数据绑定设置 MainWindowDataContext.UserName
值的确切时间。
1.放置断点
打开 MainWindowDataContext.cs
文件,并找到 UserName
属性所在的行。
public string UserName { get; set; }
对 Setter 设置断点,具体方法为将插入点移到 set
文本内并按 F9。 也可以通过右键单击“set
”,并选择“断点”/“插入断点”来实现。
2.在调试模式下运行应用
接下来,在调试模式下运行应用(按 F5 或选择“调试”/“开始调试”)。 在 TextBox
中键入一些内容,并注意不要命中断点。 如果按 Tab 键,它会将输入焦点移到下一个控件(在此示例中为按钮)。 TextBox
失去焦点会更新绑定,进而导致断点被命中。
3.将绑定更改为在用户每次击键时更新
停止调试(按 Shift+F5 或选择“调试”/“停止调试”)。
为了提供有关“提交”按钮启用时间的准确反馈,不能等到 TextBox
失去焦点。 幸运的是,可以更改绑定行为。 可以强制它在文本属性每次更改时都更新 UserName
属性(这是源,因为讨论的是 TwoWay
绑定)。 需要更改绑定的 UpdateSourceTrigger
,它默认设为 LostFocus
。 UpdateSourceTrigger
定义导致源更新的环境。
打开 MainWindow.xaml
,找到 TextBox
方法。 然后,通过添加 UpdateSourceTrigger=PropertyChanged
来更改绑定。 整个 TextBox
标记现在应如下所示:
<TextBox Name="tbName"
Margin="10"
Width="150"
VerticalAlignment="Center"
Text="{Binding UserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
如果现在调试应用,可以看到每次击键和文本更改都会命中断点。 太棒了!
你可能还记得,使用 UI 到 UI 绑定来显示问候语时,每次击键都触发了绑定。 在这种情况下,绑定是对 TextBlock
定义,因此源是 TextBox.Text
属性,它确实会在用户每次击键时更改。 UpdateSourceTrigger
影响另一个方向的数据流。 它从绑定源流向定义了绑定的控件(绑定目标)。
5.添加 IsSubmitAllowed
属性
接下来,添加指明是否允许提交窗体的布尔属性。 打开 MainWindowDataContext.cs
,并向 MainWindowDataContext
类添加新属性。
public bool IsSubmitAllowed => !string.IsNullOrWhiteSpace(UserName);
此属性执行的是一个简单的验证。 如果输入的文本不为 null、空或仅包含空格字符,就接受它作为用户名。
6. 在 UserName
每次更改后重新评估 IsSubmitAllowed
必须建议 UI 框架,何时重新评估此属性并在 UI 上反映它。 触发此重新评估的最佳方式是在 UserName
属性的 Setter 中调用 RaisePropertyChanged
。 必须先将 Setter 转换为完整属性,然后才能向 Setter 添加代码。 将 UserName
属性替换为以下代码:
private string? _userName;
public string? UserName
{
get { return _userName; }
set
{
_userName = value;
RaisePropertyChanged(nameof(IsSubmitAllowed));
}
}
我们没有对此属性使用 INotifyPropertyChanged
,因为没有出现通过代码更改 UserName
属性的情况。 不过,每当 TextBox
中的文本更改时,必须指示 UI,IsSubmitAllowed
属性可能已更改并应重新接受评估。
7.将 IsSubmitAllowed
属性绑定到按钮的 IsEnabled
属性
至此,代码已完成。 返回到 MainWindow.xaml
,并找到“提交”按钮。 添加 IsEnabled
属性,这样按钮的 XAML 现在如下所示:
<Button Margin="10"
VerticalAlignment="Center"
Click="OnSubmitClicked"
IsEnabled="{Binding IsSubmitAllowed}">Submit</Button>
8.运行应用
如果现在运行应用,应该会看到“提交”按钮默认处于禁用状态。 只要你在其中键入内容,此按钮就会立即启用。
虽然此示例执行的是一些基本的验证,但 WPF 有一组丰富的验证功能,后面的模块将展示这些功能。
总结
本课介绍了如何调试绑定。 你不仅了解了 UpdateSourceTrigger
绑定选项,还看到了更多的数据绑定示例。 此外,本课还举例介绍了如何在正确使用数据绑定的情况下,更改 UI 的外观和行为,而不影响 C# 代码。
下一课将探究如何使用数据绑定来显示列表中的多个项。