TextBox MVVM DataBinding - PullRequest
       1

TextBox MVVM DataBinding

0 голосов
/ 25 января 2012

Я пишу приложение калькулятора WPF. В этом приложении у меня есть TextBox, который получает и устанавливает ввод в соответствии с событием OnWindowKeyDown (ввод вставляется / проверяется и возвращается в TextBox в качестве пользовательского типа).

например, если пользователь вводит:

3-> validate == true--> print to TextBox '3'
y-> validate == false -> ignore
3-> validate == true --> print to TeextBox "33"

Я хочу получить входной символ за символом (у меня есть класс State Pattern, который реагирует на каждый добавленный символ), но мне нужно вернуть результат в виде строки.

Как я могу перенести мои данные из текстового поля и в него с помощью MVVM design?

Ответы [ 3 ]

2 голосов
/ 25 января 2012

Вы можете связать свои TextBoxes с Properties на ViewModel и использовать INotifyPropertyChanged события для проверки / модификации / чего угодно.

Вы можете обновить свойства из пользовательского интерфейса или фона, и он будет автоматически обновляться для пользователя.

1 голос
/ 29 марта 2012

Проблема с использованием ValueConverter заключается в том, что вы полагаетесь на слой Presentation в том, что похоже на доменную логику.Вы говорите, что у вас есть какой-то класс шаблонов состояний, который действительно звучит как часть модели (первая буква «M» в MVVM).

Если для привязки установлено значение {Binding .... UpdateSourceTrigger =PropertyChanged} вы будете получать значение, отправляемое вам View Model каждый раз, когда пользователь вводит один символ.Затем вам нужно проверять каждый вызов к установщику.

Далее, есть элемент / ошибка в элементе управления TextBox.TextBox не будет прослушивать события PropertyChanged для привязки, если она была источником изменения.Это означает, что если вы введете «y», и ваш установщик фактически установит свойство на «», а затем вызовет событие PropertyChanged, вы все равно увидите «y»: (

Есть сообщение, которое смотрит на это (/2389790/prinuditelno-ne-rabotaet-bolshe-tekstovogo-polya-wpf-v-net-4-0) но поскольку они используют события, они не выполняют MVVM.

После того, как я только что сделал это для проекта WPF, у меня появилось свойство Attached. Вся логика была в моей модели, которую обернул мой ViewModel.был в состоянии выполнить модульное тестирование моей логики, а также добавить присоединенное свойство к стилю, чтобы я мог многократно использовать его много раз.

Код, который я написал, выглядит следующим образом.

public sealed class TextBoxBehaviour : DependencyObject
{
    #region CoerceValue Attached property

    public static bool GetCoerceValue(DependencyObject obj)
    {
        return (bool)obj.GetValue(CoerceValueProperty);
    }
    public static void SetCoerceValue(DependencyObject obj, bool value)
    {
        obj.SetValue(CoerceValueProperty, value);
    }

    /// <summary>
    /// Gets or Sets whether the TextBox should reevaluate the binding after it pushes a change (either on LostFocus or PropertyChanged depending on the binding).
    /// </summary>
    public static readonly DependencyProperty CoerceValueProperty =
        DependencyProperty.RegisterAttached("CoerceValue", typeof(bool), typeof(TextBoxBehaviour), new UIPropertyMetadata(false, CoerceValuePropertyChanged));

    static void CoerceValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var textbox = d as TextBox;
        if (textbox == null) 
            return;

        if ((bool)e.NewValue)
        {
            if (textbox.IsLoaded)
            {
                PrepareTextBox(textbox);
            }
            else
            {
                textbox.Loaded += OnTextBoxLoaded;
            }
        }
        else
        {
            textbox.TextChanged -= OnCoerceText;
            textbox.LostFocus-= OnCoerceText;
            textbox.Loaded -= OnTextBoxLoaded;
        }
    }

    static void OnTextBoxLoaded(object sender, RoutedEventArgs e)
    {
        var textbox = (TextBox)sender;
        PrepareTextBox(textbox);
        textbox.Loaded -= OnTextBoxLoaded;
    }

    static void OnCoerceText(object sender, RoutedEventArgs e)
    {
        var textBox = (TextBox)sender;
        var selectionStart = textBox.SelectionStart;
        var selectionLength = textBox.SelectionLength;

        textBox.GetBindingExpression(TextBox.TextProperty).UpdateTarget();

        if (selectionStart < textBox.Text.Length) textBox.SelectionStart = selectionStart;
        if (selectionStart + selectionLength < textBox.Text.Length) textBox.SelectionLength = selectionLength;
    }

    private static void PrepareTextBox(TextBox textbox)
    {
        var binding = textbox.GetBindingExpression(TextBox.TextProperty).ParentBinding;
        var newBinding = binding.Clone();
        newBinding.ValidatesOnDataErrors = true;
        textbox.SetBinding(TextBox.TextProperty, newBinding);

        if (newBinding.UpdateSourceTrigger == UpdateSourceTrigger.PropertyChanged)
        {
            textbox.TextChanged += OnCoerceText;
        }
        else if (newBinding.UpdateSourceTrigger == UpdateSourceTrigger.LostFocus || newBinding.UpdateSourceTrigger == UpdateSourceTrigger.Default)
        {
            textbox.LostFocus += OnCoerceText;
        }
    }
    #endregion
}

тогда вы простонеобходимо реализовать установщик (как вы, кажется, уже) и добавить в текстовое поле прикрепленное свойство, привязанное к вашей модели представления.

<TextBox Text="{Binding Number, UpdateSourceTrigger=PropertyChanged}"
         myNamespace:TextBoxBehaviour.CoerceValue="True"/>
1 голос
/ 25 января 2012

Это должно быть достаточным для привязки свойства Text TextBox к ViewModel.

Например:

//ViewModel 
public class MyViewModel : INotifyPropertyChanged
{
     private string textBoxText = string.Empty;
     public string TextBoxText 
     {
        get {return textBoxText;}
        set {
           textBoxText = value;
           OnPropertyChanged("TextBoxText "..);
        }
     }
}

Свяжите MyViewModel с DataContext вашего Form, TextBox или любым другим ... вкратце сделайте его доступным для вашего TextBoxкаким-то образом.

Определите Converter, кого будут вызывать методы каждый время Text свойство TextBox установлено.

public class TextContenyConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {

        // validate input and return appropriate value
    }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

После привязки в XAML с учетом того, что DataContext является объектом типа MyViewModel

, где TextContenyConverterObject является определенным объектом типа TextContenyConverterкак статический ресурс.

Это всего лишь пример.

Это - еще одно хорошее объяснение ValueConverters.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...