【问题标题】:How to work around UpdateSourceTrigger ignored in NumberBox如何解决 NumberBox 中忽略的 UpdateSourceTrigger
【发布时间】:2020-09-22 14:29:10
【问题描述】:

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

我的数据表单范例是在实际保存数据更改之前不显示 保存 按钮,但是 由于在焦点离开控件之前数据源不会更新,因此在用户首先移动到不同的输入控件之后,保存按钮才可用。

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

这是最小的例子,如果你使用微调器来改变值,按钮是可用的,如果你只在控件中输入你必须点击按钮两次,一次启用它(提交值更改)然后再一次,现在按钮可用了。

如果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;
    }  
}

【问题讨论】:

    标签: uwp binding uwp-xaml


    【解决方案1】:

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

    control style definition of NumberBox中,主体是TextBox。如果你想干预这个过程,你需要得到这个TextBox

    1.定义视觉方法

    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;
        }
    }
    

    【讨论】:

    • 不尊重UpdateSourceTrigger=PropertyChanged 就像其他所有数据输入控件一样,这真是太糟糕了,但这是我希望的最佳解决方案,非常感谢!
    • 这个讨论:stackoverflow.com/a/64165206/1690217 强调了为什么我认为这是NumberBox 行为中的一个错误。但我现在明白了如何使用x:Bind 会使如何在内部实现这一点进一步复杂化,因为如果输入控件间接绑定到外部可见的Value 属性,则内部实现无法使用UpdateSource 信息。
    • NumberBox STILL 的绑定方式与标准 TextBox 不同,这太荒谬了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    • 1970-01-01
    • 2012-02-14
    • 2019-10-28
    • 2020-11-24
    • 1970-01-01
    相关资源
    最近更新 更多