创建交互式 UI

已完成

Tech logo.

在前面几课中,你生成了一个提示用户输入用户名的简单窗体 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,它默认设为 LostFocusUpdateSourceTrigger 定义导致源更新的环境。

打开 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 有一组丰富的验证功能,后面的模块将介绍这些功能。

Screenshot of app, with Submit button disabled.

9.隐藏“提交”按钮

你或设计人员可能会决定更进一步,即在用户可以按“提交”按钮前隐藏它。 这是一种简单更改,所以让我们现在就进行吧。 只需编辑 XAML,并将 IsEnabled 更改为 Visibility 即可。

Screenshot of app, with Submit button hidden.

不过,如果键入几个字符,便会发现整个 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# 代码。

下一课将探究如何使用数据绑定来显示列表中的多个项。

Tech logo.

在前面几课中,你创建了一个提示用户输入用户名的简单窗体 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,它默认设为 LostFocusUpdateSourceTrigger 定义导致源更新的环境。

打开 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 有一组丰富的验证功能,后面的模块将展示这些功能。

Screenshot of app, with Submit button disabled.

总结

本课介绍了如何调试绑定。 你不仅了解了 UpdateSourceTrigger 绑定选项,还看到了更多的数据绑定示例。 此外,本课还举例介绍了如何在正确使用数据绑定的情况下,更改 UI 的外观和行为,而不影响 C# 代码。

下一课将探究如何使用数据绑定来显示列表中的多个项。