새 문자가 TextBox에 입력되는 즉시 데이터 바인딩 업데이트를 만들려면 어떻게해야합니까?
나는 WPF의 바인딩에 대해 배우고 있으며 이제 (희망적으로) 간단한 문제에 갇혀 있습니다.
Path 속성을 설정할 수있는 간단한 FileLister 클래스가 있으며 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 이벤트를 처리해야합니까?
답변
텍스트 상자 바인딩에서해야 할 일은 설정하는 것뿐입니다 UpdateSourceTrigger=PropertyChanged
.
답변
UpdateSourceTrigger
속성을 다음과 같이 설정해야 합니다.PropertyChanged
<TextBox Text="{Binding Source={StaticResource fileLister}, Path=Path, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Height="25" Margin="12,12,12,0" VerticalAlignment="Top"/>
답변
C #이 없으면 클래스가 아닌 TextBox 용 XAML로 충분합니다. 따라서 TextBox의 길이를 쓰는 TextBlock의 속성을 모니터링합니다.
Binding Text.Length
<StackPanel>
<TextBox x:Name="textbox_myText" Text="123" />
<TextBlock x:Name="tblok_result" Text="{Binding Text.Length, ElementName=textbox_myText}"/>
</StackPanel>
답변
갑자기 슬라이더와 관련 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;
}
}
}
XAML에서
<Window.Resources>
<local:ToOneDecimalConverter x:Key="ToOneDecimalConverter"/>
</Window.Resources>
추가로 정의 된 TextBox
<TextBox x:Name="TextSlidVolume"
Text="{Binding ElementName=SlidVolume, Path=Value,
Converter={StaticResource ToOneDecimalConverter},Mode=TwoWay}"
/>