В моем проекте Silverlight я создаю текстовые поля, которые имеют двустороннюю привязку к данным для некоторого контекста во время выполнения. Привязка в одном направлении ( от источника к цели ), кажется, работает нормально, но другое направление ( от цели назад к источнику ) не дает никакого эффекта.
Это контекст данных:
public class Leg : INotifyPropertyChanged {
private string passengers;
public string Passengers {
get { return passengers; }
set {
// here I have a breakpoint.
passengers = value;
FirePropertyChanged("Passengers");
}
}
private void FirePropertyChanged (string property) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Затем в другом месте я создаю новый элемент управления TextBox вместе с привязкой для него:
Binding passengersBinding = new Binding();
// viewModelLeg is an instance of the class Leg from above
passengersBinding.Source = viewModelLeg;
passengersBinding.Path = new PropertyPath("Passengers");
passengersBinding.Mode = BindingMode.TwoWay;
legItem.paxTextBox.SetBinding(TextBox.TextProperty, passengersBinding);
Теперь, когда я изменяю значение строки «Пассажиры», соответствующее текстовое поле, привязанное к нему, корректно обновляет свой текст. Так что здесь все хорошо.
Но когда я вручную изменяю текст текстового поля, а затем заставляю текстовое поле терять фокус, ничего не происходит - то есть не происходит двустороннего связывания - не распространяется нисходящее распространение нового текстового значения текстового поля к источник!
У меня есть точка останова в установщике атрибута пассажиров (отмечена комментарием точки останова выше). Когда я получаю все это правильно, механизм привязки также использует этот общедоступный установщик, когда целевое значение привязки изменилось, чтобы обновить источник - поэтому, когда это происходит, должна быть достигнута точка останова. Но он не делает! Так что, похоже, я могу делать то, что хочу, с моим текстовым полем (играть с фокусом или нажать клавишу ввода), оно никогда не обновляет его источник.
Я что-то наблюдаю? В моем коде или в моих мыслях должна быть заглавная ошибка ... я был бы очень благодарен за любые идеи ...
EDIT:
Далее я попытаюсь продемонстрировать, как я создаю свои объекты XAML и мои объекты DataContext. Поскольку я создаю элементы управления XAML и их привязки во время выполнения, я не нашел хорошего решения для реализации подхода MVVM очень хорошо. Поэтому я делаю следующее (что, возможно, не лучший способ сделать это):
Ситуация, которую я моделирую, состоит в том, что у меня есть UserControl (называемый LegItem), который состоит (в основном) из текстовых полей. Во время выполнения пользователь может создать столько пользовательских контролов, сколько пожелает (один за другим).
На моей стороне ViewModel у меня есть класс (называемый Leg), который служит в качестве ViewModel ровно для одного LegItem. Поэтому, когда я говорю n (XAML-) LegItems, тогда у меня также есть n экземпляров Leg. Я храню эти объекты ног в списке.
Поэтому каждый раз, когда пользователь нажимает кнопку «Добавить новую ногу», я делаю следующее:
// here we are inside the applications view in an .xaml.cs file
public void AddLeg () {
// this is going to serve as the ViewModel for the new LegItem
// I am about to create.
Leg leg = viewModel.insertLeg();
// here I am starting to create the visual LegItem. The ViewModel object
// I have created in the previous step is getting along with.
createLegItem(leg);
}
// the primary job here is to bind each contained textbox to its DataContext.
private LegItem createLeg (Leg viewModelLeg) {
// create the visual leg item control element
// which is defined as a XAML UserControl.
LegItem legItem = new LegItem();
Binding passengersBinding = new Binding();
// viewModelLeg is an instance of the class Leg from above
passengersBinding.Source = viewModelLeg;
passengersBinding.Path = new PropertyPath("Passengers");
passengersBinding.Mode = BindingMode.TwoWay;
legItem.paxTextBox.SetBinding(TextBox.TextProperty, passengersBinding);
}
// on the viewModel side there is this simple method that creates one Leg object
// for each LegItem the View is creating and stores inside a simple list.
public Leg InsertLeg () {
Leg leg = new Leg();
legList.add(leg)
return leg;
}