如何解决在NumberBox中忽略的UpdateSourceTrigger

问题描述

我已尝试在UWP应用程序中将数据绑定到NumberBox上的UpdateSourceTrigger设置为PropertyChanged

我的数据形式范例是在实际更改数据之前不显示 Save 按钮,但是 由于直到焦点离开控件后才更新数据源,因此直到用户首先移至另一个输入控件之后,保存按钮才可用。

  • 用户无法单击保存按钮,因为它已被禁用,因此不会触发焦点更改。

这是最小的示例,如果使用微调器更改值,则按钮可用;如果仅键入控件,则必须单击两次按钮,一次才能启用它(以提交值更改)现在,按钮再次可用。

如果UpdateSourceTrigger不起作用,如何提交更改,以便用户应该可用时第一次单击按钮,因此在焦点更改之前?

<Page
    x:Class="App3.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App3"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Page.DataContext>
        <local:DataClass/>
    </Page.DataContext>
    <Grid>
        <StackPanel>
            <muxc:NumberBox Value="{Binding Value,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SpinButtonPlacementMode="Inline"/>
            <Button IsEnabled="{Binding NotZero,Mode=OneWay}" Click="Button_Click">Click if Not Zero</Button>
        </StackPanel>
    </Grid>
</Page>
using System;
using System.ComponentModel;
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 App3
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        public DataClass Model { get => this.DataContext as DataClass; }

        private async void Button_Click(object sender,RoutedEventArgs e)
        {
            var msg = new Windows.UI.Popups.MessageDialog($"Value: {Model.Value}");
            await msg.ShowAsync();
        }
    }

    public class DataClass : INotifyPropertyChanged
    {
        public double Value
        {
            get => _v;
            set
            {
                _v = value;
                PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(nameof(Value)));
                PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(nameof(NotZero)));
            }
        }
        private double _v;
        public bool NotZero { get => _v != 0; }
        public event PropertyChangedEventHandler PropertyChanged;
    }  
}

解决方法

这是NumberBox的默认行为,通常用于在输入完成后对NumberBox中的内容做出一些判断。

control style definition of NumberBox中,主体为TextBox。如果您要干预此过程,则需要获得此TextBox

1。定义的Viusal方法

public static class StaticExtension
{
    public static FrameworkElement VisualTreeFindName(this DependencyObject element,string name)
    {
        if (element == null || string.IsNullOrWhiteSpace(name))
        {
            return null;
        }
        if (name.Equals((element as FrameworkElement)?.Name,StringComparison.OrdinalIgnoreCase))
        {
            return element as FrameworkElement;
        }
        var childCount = VisualTreeHelper.GetChildrenCount(element);
        for (int i = 0; i < childCount; i++)
        {
            var result = VisualTreeHelper.GetChild(element,i).VisualTreeFindName(name);
            if (result != null)
            {
                return result;
            }
        }
        return null;
    }
}

2。附加TextChanged处理程序

Xaml

<muxc:NumberBox ... Loaded="NumberBox_Loaded"/>

Xaml.cs

private void NumberBox_Loaded(object sender,RoutedEventArgs e)
{
    var box = sender as NumberBox;
    var textBox = box.VisualTreeFindName<TextBox>("InputBox");
    textBox.TextChanged += TextBox_TextChanged;
}

private void TextBox_TextChanged(object sender,TextChangedEventArgs e)
{
    string text = (sender as TextBox).Text;
    bool isNumber = !text.Any(t => !char.IsDigit(t));
    if (isNumber)
    {
        double.TryParse(text,out double value);
        if (value != Model.Value)
            Model.Value = value;
    }
}