Как мне привязать текстовое поле XAML либо к входным данным другого текстового поля, либо к его собственным входным данным, а затем сохранить входные данные в объект данных в MVVM?

#c# #wpf #xaml #mvvm

#c# #wpf #xaml #mvvm

Вопрос:

У меня есть 2 пары текстовых полей для пользовательского ввода (см. XAML ниже). В подавляющем большинстве случаев входные данные для A1 и A2 будут идентичны B1 и B2, поэтому я добавил привязки для txtDataB1 и txtDataB2 для «зеркального отображения» входных данных для A1 и A2, что работает в пользовательском интерфейсе. Данные, введенные в A1 / A2, сохраняются нормально, поскольку они привязаны к dataStore , но у меня есть некоторые проблемы:

Как мне сохранить значения, введенные в txtDataB1 и txtDataB2 (либо из ручного ввода пользователем, либо зеркальные данные из A1 / A2) в dataStore объект? Я недостаточно знаком с XAML / MVVM / etc, чтобы знать, есть ли «чистый XAML» способ сделать это с помощью многосвязей или чего-то еще, или если бы была какая-то логика, которую я должен был бы создать / вызвать в модели представления.

 <!-- Data A -->
<TextBox Name="txtDataA1" Text="{Binding dataStore.A1}" />
<TextBox Name="txtDataA2" Text="{Binding dataStore.A2}" />

<!-- Data B -->
<TextBox Name="txtDataB1" Text="{Binding ElementName=txtDataA1, Path=Text, Mode=OneWay}" />
<TextBox Name="txtDataB2" Text="{Binding ElementName=txtDataA2, Path=Text, Mode=OneWay}" />
  

Комментарии:

1. Я думаю, это должно сработать: привязать txtDataB? в хранилище данных.B? (реализация INotifyPropertyChanged), которое, в свою очередь, изменяется при изменении хранилища данных.A?.

2. Это не привело бы к обновлению пользовательского интерфейса, не так ли? Или, я думаю, когда срабатывает INotifyPropertyChanged, я мог бы обновить пользовательский интерфейс вручную

3. Реализация INotifyPropertyChanged означает, что вы вызываете PropertyChanged — это обновило бы пользовательский интерфейс.

Ответ №1:

Забудьте о попытке реализовать подобную логику приложения в «чистом XAML» и вместо этого реализуйте ее в модели представления. XAML — это язык разметки.

Параметр A1 должен быть установлен B1 , а параметр A2 должен быть установлен B2 , например:

 public class ViewModel : INotifyPropertyChanged
{
    private string _a1;
    public string A1
    {
        get { return _a1; }
        set { _a1 = value; NotifyPropertyChanged(); B1 = value; }
    }

    private string _b1;
    public string B1
    {
        get { return _b1; }
        set { _b1 = value; NotifyPropertyChanged(); }
    }

    // the same for A2 and B2

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
  

XAML:

Сохранение данных — это тогда просто вопрос получения значений из свойств B1 и B2 , не имеет значения, как они были установлены.

Комментарии:

1. Это имеет смысл, однако у меня нет двух независимых свойств, B1 и B2 в виртуальной машине они находятся внутри, ObserveableCollection<DataStore> где DataStore — пользовательский объект для этого проекта.

2. @zakparks31191: Я не понимаю вашей проблемы. Если у вас нет свойств, вы, конечно, должны добавить их к любому объекту, к которому вы привязываете.

3. Да, это был правильный способ сделать это. Основная проблема заключалась в том, что структура MVVM всего этого проекта была выполнена неправильно, поэтому после переписывания, а затем реализации этого предложения, все сработало, как ожидалось.

Ответ №2:

Это можно решить с помощью двухполосной привязки, но текстовое поле по LostFocus умолчанию обновляется, также необходимо изменить его UpdateSourceTrigger , код будет следующим:

 <!-- Data A -->
<TextBox Name="txtDataA1" Text="{Binding dataStore.A1, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Name="txtDataA2" Text="{Binding dataStore.A2, UpdateSourceTrigger=PropertyChanged}"/>

<!-- Data B -->
<TextBox Name="txtDataB1" Text="{Binding ElementName=txtDataA1, Path=Text, Mode=TwoWay}" />
<TextBox Name="txtDataB2" Text="{Binding ElementName=txtDataA2, Path=Text, Mode=TwoWay}" />
  

Комментарии:

1. Это дает те же результаты, что и код, который я привел в вопросе.

2. @zakparks31191 Реализовали ли вы NotifyPropertyChanged для хранилища данных. A1?