Двухстороннее связывание не работает - PullRequest
2 голосов
/ 19 января 2012

В моем проекте 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;
}

1 Ответ

1 голос
/ 19 января 2012

Новый ответ

Поскольку вы упомянули, что ваша привязка на самом деле была к пользовательской UserControl, а не TextBox, я бы посоветовал изучить XAML вашей UserControlи убедившись, что он правильно связывает данные

Старый ответ

Я провел быстрый тест с новым проектом Silverlight и заметил, что запускаемый проект имеет значение SilverlightApplication1.Web, а не SilverlightApplication.

Это означает, что точка останова в установщике фактически не будет достигнута при запуске проекта.Вы заметите, что круг точки останова - это просто контур, и цвет не заполнен. Если вы наведете курсор на него, он скажет

В настоящий момент точка останова не будет достигнута.Для этого документа не было загружено ни одного символа

Если я запускаю SilverlightApplication1 вместо .Web версии, точка останова получает удар.

Свойство равно и изменяется правильно независимо от того, какую версию я запускаю, однако точка останова не будет достигнута, если я начну проект с версией .Web.Я подозреваю, что это ваша проблема.

...