C# 在每个新字符上创建 WPF TextBox 绑定?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10619596/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 14:32:28  来源:igfitidea点击:

Making a WPF TextBox binding fire on each new character?

c#wpfxamldata-bindingtextbox

提问by luddet

How can I make a data binding update as soon as a new character is typed in a TextBox?

在 TextBox 中输入新字符后,如何立即进行数据绑定更新?

I'm learning about bindings in WPF and now I've become stuck on a (hopefully) simple matter.

我正在学习 WPF 中的绑定,现在我陷入了一个(希望如此)简单的问题。

I have a simple FileLister class where you can set a Path property, and then it will give you a listing of files when you access the FileNames property. Here is that class:

我有一个简单的 FileLister 类,您可以在其中设置 Path 属性,然后在您访问 FileNames 属性时它会为您提供文件列表。这是那个类:

class FileLister:INotifyPropertyChanged {
    private string _path = "";

    public string Path {
        get {
            return _path;
        }
        set {
            if (_path.Equals(value)) return;
            _path = value;
            OnPropertyChanged("Path");
            OnPropertyChanged("FileNames");
        }
    }

    public List<String> FileNames {
        get {
            return getListing(Path);
        }
    }

    private List<string> getListing(string path) {
        DirectoryInfo dir = new DirectoryInfo(path);
        List<string> result = new List<string>();
        if (!dir.Exists) return result;
        foreach (FileInfo fi in dir.GetFiles()) {
            result.Add(fi.Name);
        }
        return result;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string property) {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) {
            handler(this, new PropertyChangedEventArgs(property));
        }
    }
}

I'm using the the FileLister as a StaticResource in this very simple app:

我在这个非常简单的应用程序中使用 FileLister 作为 StaticResource:

<Window x:Class="WpfTest4.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfTest4"
    Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:FileLister x:Key="fileLister" Path="d:\temp" />
    </Window.Resources>
    <Grid>
        <TextBox Text="{Binding Source={StaticResource fileLister}, Path=Path, Mode=TwoWay}"
        Height="25" Margin="12,12,12,0" VerticalAlignment="Top" />
        <ListBox Margin="12,43,12,12" Name="listBox1" ItemsSource="{Binding Source={StaticResource ResourceKey=fileLister}, Path=FileNames}"/>
    </Grid>
</Window>

The binding is working. If I change the value in the textbox and then click outside of it, the listbox contents will update (as long as the path exists).

绑定正在工作。如果我更改文本框中的值,然后单击它的外部,则列表框内容将更新(只要路径存在)。

The problem is that I would like to update as soon as a new character is typed, and not wait until the textbox lose focus.

问题是我想在输入新字符后立即更新,而不是等到文本框失去焦点。

How can I do that? Is there a way to do this directly in the xaml, or do I have to handle TextChanged or TextInput events on the box?

我怎样才能做到这一点?有没有办法直接在 xaml 中执行此操作,或者我是否必须处理框上的 TextChanged 或 TextInput 事件?

采纳答案by Dave

In your textbox binding, all you have to do is set UpdateSourceTrigger=PropertyChanged.

在您的文本框绑定中,您所要做的就是设置UpdateSourceTrigger=PropertyChanged.

回答by Eduardo Brites

You have to set the UpdateSourceTriggerproperty to PropertyChanged

您必须将UpdateSourceTrigger属性设置为PropertyChanged

<TextBox Text="{Binding Source={StaticResource fileLister}, Path=Path, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
         Height="25" Margin="12,12,12,0" VerticalAlignment="Top"/>

回答by Erhy

Suddenly the data binding between slider and associated TextBox made troubles. At last I found the reason and could fix it. The converter I use:

突然之间滑块和关联的TextBox 之间的数据绑定产生了麻烦。最后我找到了原因并可以解决它。我使用的转换器:

using System;
using System.Globalization;
using System.Windows.Data;
using System.Threading;

namespace SiderExampleVerticalV2
{
    internal class FixCulture
    {
        internal static System.Globalization.NumberFormatInfo currcult
                = Thread.CurrentThread.CurrentCulture.NumberFormat;

        internal static NumberFormatInfo nfi = new NumberFormatInfo()
        {
            /*because manual edit properties are not treated right*/
            NumberDecimalDigits = 1,
            NumberDecimalSeparator = currcult.NumberDecimalSeparator,
            NumberGroupSeparator = currcult.NumberGroupSeparator
        };
    }

    public class ToOneDecimalConverter : IValueConverter
    {
        public object Convert(object value,
            Type targetType, object parameter, CultureInfo culture)
        {
            double w = (double)value;
            double r = Math.Round(w, 1);
            string s = r.ToString("N", FixCulture.nfi);
            return (s as String);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string s = (string)value;
            double w;
            try
            {
                w = System.Convert.ToDouble(s, FixCulture.currcult);
            }
            catch
            {
                return null;
            }
            return w;
        }
    }
}

In XAML

在 XAML 中

<Window.Resources>
    <local:ToOneDecimalConverter x:Key="ToOneDecimalConverter"/>
</Window.Resources>

further the defined TextBox

进一步定义的 TextBox

<TextBox x:Name="TextSlidVolume"
    Text="{Binding ElementName=SlidVolume, Path=Value,
        Converter={StaticResource ToOneDecimalConverter},Mode=TwoWay}"
/>

回答by sg6336

Without C#, it's enough in XAML for TextBox, not for class. So, monitoring the property of TextBlock, where writing length of TextBox: Binding Text.Length

如果没有 C#,在 XAML 中用于 TextBox 就足够了,而不是用于类。所以,监控TextBlock的属性,其中TextBox的写入长度: Binding Text.Length

<StackPanel>
  <TextBox x:Name="textbox_myText" Text="123" />
  <TextBlock x:Name="tblok_result" Text="{Binding Text.Length, ElementName=textbox_myText}"/>
</StackPanel>