当用户单击 CommandBar 上的 AppBarButton 时,最后一个具有焦点的文本框中的数据不会更新(UWP)

When user clicks on AppBarButton on CommandBar, data in the last textbox that had focus is not updated (UWP)

我有一个简单的数据页面,用户在其中填写 2 个字段(名字和姓氏)并单击 CommandBar 上的保存 AppBarButton

这两个字段都使用 x:BindMode=TwoWay 到 load/update 的值。

如果用户填写名字文本框,然后填写姓氏文本框并点击命令栏上的保存 AppBar 按钮,而焦点仍在姓氏文本框上,只有名字被更新.

不过,我还在页面上创建了一个常规 Button,如果用户执行相同的操作并改为使用此按钮,则两个字段都会按预期更新。

如何让 CommandBar 上的 AppBarButton 以与常规按钮相同的方式工作并更新所有数据而无需在后面添加大量代码?

这是我的简单 class 定义:

public class UserData
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

这是 XAML 页面:

<Page
    x:Class="mySampleApp.MainPage"
    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"
    x:Name="MyPage"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

        <Grid.RowDefinitions>
            <RowDefinition  Height="Auto"/>
            <RowDefinition  Height="Auto"/>
            <RowDefinition  Height="Auto"/>
            <RowDefinition  Height="Auto"/>
        </Grid.RowDefinitions>

        <CommandBar Grid.Row="0"  DefaultLabelPosition="Right" >
            <!-- Save button on a command bar-->
            <AppBarButton Icon="Save" Label="Save" LabelPosition="Default" Click="saveStuff_Click" />
        </CommandBar>

        <!-- Sample Data to save-->
        <TextBox x:Name="txtFirstName" Grid.Row="1" Header="Enter Your First Name" Text="{x:Bind currentUserData.FirstName, Mode=TwoWay}" PlaceholderText="First Name"/>
        <TextBox x:Name="txtLastName" Grid.Row="2" Header="Enter Your Last Name" Text="{x:Bind currentUserData.LastName, Mode=TwoWay}" PlaceholderText="Last Name"/>

        <!-- Save button using a regular button that calls the same function-->
        <Button x:Name="saveStuff" Grid.Row="3" Content="Save" Click="saveStuff_Click" />

    </Grid>
</Page>

下面是代码:

using Newtonsoft.Json;
using System;
using Windows.Storage;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace mySampleApp
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        //variables to use in XAML x:Bind
        private UserData currentUserData = new UserData();

        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void saveStuff_Click(object sender, RoutedEventArgs e)
        {
            var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("sampledata.json", CreationCollisionOption.ReplaceExisting);
            await FileIO.WriteTextAsync(file, JsonConvert.SerializeObject(currentUserData, Formatting.Indented));
            var dialog = new MessageDialog("Data saved to: " + file.Path.ToString() + Environment.NewLine + "Data Saved: FirstName: " + currentUserData.FirstName + "; LastName: " + currentUserData.LastName);
            await dialog.ShowAsync();
        }
    }
}

in the official documentation (scroll down to UpdateSourceTrigger) 所述,TextBox.Text 上的 x:Bind 等待文本框失去焦点以将其内容转发到 Viewodel。与从文本框中窃取上下文的普通 Button 相比,似乎在使用 AppBarButton 时焦点停留在文本框上(正如您自己提到的),因此绑定 属性 永远不会更新。

将绑定的 UpdateSourceTrigger 设置为 PropertyChanged 可能会解决问题,因为它会强制在每次按键时刷新绑定,但不幸的是 x:Bind 不支持此操作。所以我猜你最好的选择是使用传统的 Binding:

Text="{Binding currentUserData.LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

我能够通过将所有文本框绑定保持原样(使用 x:Bind)并仅使用 AllowFocusOnInteraction="True" 更新 CommandBar 上的 AppBarButton 来解决此问题。

现在看起来像这样,一切都按预期工作:

<AppBarButton AllowFocusOnInteraction="True" Icon="Save" Label="Save" LabelPosition="Default" Click="saveStuff_Click" />