Tạo lửa liên kết WPF TextBox trên mỗi ký tự mới?


83

Làm cách nào để cập nhật liên kết dữ liệu ngay sau khi một ký tự mới được nhập vào TextBox?

Tôi đang tìm hiểu về các ràng buộc trong WPF và bây giờ tôi gặp khó khăn về một vấn đề (hy vọng) đơn giản.

Tôi có một lớp FileLister đơn giản, nơi bạn có thể đặt thuộc tính Đường dẫn và sau đó nó sẽ cung cấp cho bạn danh sách các tệp khi bạn truy cập thuộc tính FileNames. Đây là lớp đó:

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

Tôi đang sử dụng FileLister làm StaticResource trong ứng dụng rất đơn giản này:

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

Ràng buộc đang hoạt động. Nếu tôi thay đổi giá trị trong hộp văn bản và sau đó nhấp vào bên ngoài nó, nội dung hộp danh sách sẽ cập nhật (miễn là đường dẫn tồn tại).

Vấn đề là tôi muốn cập nhật ngay sau khi một ký tự mới được nhập, và không đợi cho đến khi hộp văn bản mất tiêu điểm.

Làm thế nào tôi có thể làm điều đó? Có cách nào để thực hiện việc này trực tiếp trong xaml hay tôi phải xử lý các sự kiện TextChanged hoặc TextInput trên hộp không?

Câu trả lời:


144

Trong liên kết hộp văn bản của bạn, tất cả những gì bạn phải làm đã được thiết lập UpdateSourceTrigger=PropertyChanged.


1
Cảm ơn! Chính xác là giải pháp đơn giản như tôi đã hy vọng :)
luddet

Đối với tôi, nó không hoạt động ... Tôi muốn đưa văn bản trở lại giá trị trước đó, trong trường hợp nó không phải là một số. Chỉ khi được thêm IsAsync = True thì nó mới hoạt động.
Ilans

Tôi đã thử thiết lập điều này trong trình thiết kế Visual Studio (VS2015). Trong hộp thoại liên kết, tùy chọn được hiển thị khi tôi mở rộng trình mở rộng 'Cài đặt khác'. Tuy nhiên, UpdateSourceTrigger bị vô hiệu trừ khi tôi cũng đặt BindingDirection thành thứ gì đó khác với Mặc định.
Martin Brown

32

Bạn phải đặt thuộc UpdateSourceTriggertính thànhPropertyChanged

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

-1

Nếu không có C #, nó đủ trong XAML cho TextBox, không phải cho lớp. Vì vậy, theo dõi thuộc tính của TextBlock, nơi ghi độ dài của TextBox: Binding Text.

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

-2

Đột nhiên, liên kết dữ liệu giữa thanh trượt và TextBox liên quan gây ra sự cố. Cuối cùng tôi đã tìm ra lý do và có thể sửa chữa nó. Bộ chuyển đổi tôi sử dụng:

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

Trong XAML

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

hơn nữa TextBox đã xác định

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

2
Tôi nghĩ rằng bạn đã đăng câu trả lời của bạn trong câu hỏi sai. Câu hỏi ban đầu không bao gồm bất kỳ thông tin nào về thanh trượt.
GrantByrne
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.