在每个新字符上制作 WPF 文本框绑定火?

一旦在 TextBox 中键入新字符,如何进行数据绑定更新?

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

我有一个简单的 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));
}
}
}

我在这个非常简单的应用程序中使用 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>

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

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

我该怎么做? 有没有一种方法可以直接在 xaml 中实现这一点,或者我必须在框中处理 TextChanged 或 TextInput 事件?

39126 次浏览

You have to set the UpdateSourceTrigger property to PropertyChanged

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

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

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:

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

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

further the defined TextBox

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

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

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