XAML WinUI-3和C#〈>关于以下内容的说明:如何解决NumberBox中忽略UpdateSourceTrigger的问题

mzsu5hc0  于 2022-12-07  发布在  C#
关注(0)|答案(2)|浏览(169)

更新:谢谢Andrew KeepCoding的CustomNumberBox类。这真的很有帮助,而且比其他解决方案更容易使用。它不需要数据绑定就能工作。
关于Chris Schaller提出并由Richard Zhang回答的问题,我有一个澄清/用户错误:How to work around UpdateSourceTrigger ignored in NumberBox
我收到以下两个错误:
错误CS1061“NumberBox”不包含“VisualTreeFindName”的定义,并且找不到接受“NumberBox”类型的第一个参数的可访问扩展方法“VisualTreeFindName”(是否缺少using指令或程序集引用?)
错误CS 0103此处的当前上下文中不存在名称ウModel Ж。
下面是对上一个答案的扩展(虽然我的答案是命名空间记帐..)

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media;
using System;

namespace Accounting
{
    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;
        }
    }
}

下面是主窗口.xaml

<Window
    x:Class="Accounting.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Accounting"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
        <NumberBox
            x:Name="myNumberBox"
            SpinButtonPlacementMode="Compact"
            Loaded="NumberBox_Loaded"
            Value="0" />
    </StackPanel>
</Window>

这里是MainWindow.xaml.cs

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using System;
using System.Linq;
using System.Reflection; 

namespace Accounting
{
    public sealed partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.InitializeComponent();
        }

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

j1dl9f461#

您也可以创建这样的自定义控件。这里的一个缺点是它将始终作为UpdateSourceTrigger=PropertyChanged工作。

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using System.Collections.Generic;
using System.Linq;

namespace NumberBoxes;

public class CustomNumberBox : NumberBox
{
    public CustomNumberBox()
    {
        Loaded += CustomNumberBox_Loaded;
    }

    private static IEnumerable<T> FindChildrenOfType<T>(DependencyObject parent) where T : DependencyObject
    {
        if (parent is ContentControl contentControl)
        {
            if (contentControl.Content is T tContent)
            {
                yield return tContent;
            }

            if (contentControl.Content is DependencyObject dependencyObjectContent)
            {
                foreach (T grandChild in FindChildrenOfType<T>(dependencyObjectContent))
                {
                    yield return grandChild;
                }
            }
        }
        else
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(parent, i);

                if (child is T tChild)
                {
                    yield return tChild;
                }

                foreach (T grandChild in FindChildrenOfType<T>(child))
                {
                    yield return grandChild;
                }
            }
        }
    }

    private void CustomNumberBox_Loaded(object sender, RoutedEventArgs e)
    {
        if (FindChildrenOfType<TextBox>(this)
            .Where(x => x.Name is "InputBox")
            .FirstOrDefault() is TextBox inputBox)
        {
            inputBox.TextChanged += InputBox_TextChanged;
        }
    }

    private void InputBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (sender is TextBox inputBox)
        {
            Text = inputBox.Text;
        }
    }
}
6yt4nkrj

6yt4nkrj2#

错误CS1061“NumberBox”不包含“VisualTreeFindName”的定义,并且找不到接受“NumberBox”类型的第一个参数的可访问扩展方法“VisualTreeFindName”(是否缺少using指令或程序集引用?)
出现此错误是因为方法VisualTreeFindName不是泛型方法,并且在调用它时不需要<TextBox>。删除<TextBox>并将返回值强制转换为TextBox应该会起作用,并在NumberBox内为您提供名为InputBoxTextBox

if (this.ThisNumberBox.VisualTreeFindName("InputBox") is TextBox inputBox)
{
    inputBox.TextChanged += InputBox_TextChanged;
}

错误CS0103此处的当前上下文中不存在名称ウModel Ж。
出现此错误是因为代码中不存在Model。此Model只是问题中用作引用的属性。将Model替换为目标属性应该可以解决此问题。

相关问题