2
votes

In my Silverlight project I am creating textboxes which are two-way databound to some Context during runtime. The binding in one direction (from the source to the target) seems to work fine, but the other direction (from the target back to the source) is not showing any effect.

This is the data-context:

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

Then on another place I am creating a new TextBox control together with a binding for it:

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

Now when I am altering the value of the Passengers string the corresponding textbox that is bound to it is updating its text correctly. So here's everthing fine.

But when i change the text of a textbox manually and then make the textbox lose its focus, nothing happens - i.e. there is no two-way binding taking place - no down propagation of the new text-value of the textbox to the source !

I have a breakpoint at the setter of the passengers-attribute (marked with the breakpoint-comment above). When I am getting all this right the binding engine also uses this public setter when the target-value of a binding has changed to update the source - so when this happens the breakpoint must be hit. But he doesn't ! So it seems that i can do what I want with my textbox (play with the focus or press enter) it is never updating its source.

Am I overseeing something ? There must be a capital error either in my code or in my thinking.. i would be really thankful for any ideas ...

EDIT:

In the following I try to demonstrate how i create my XAML objects and my DataContext objects. Because I am creating XAML controls and their bindings at runtime I haven't found a good solution to implement the MVVM approach very well. So I am doing the following (which is maybe not the best way to do it):

The situation I am modelling is that I have a UserControl (called LegItem) which is comprised (primarely) of textboxes. At runtime the user can create as much of these userControls as hew wishes to (one after the other).

On my ViewModel side I have a class (called Leg) that serves as a ViewModel for exactly one LegItem. So when I have say n (XAML-) LegItems then I also have n Leg instances. I store these Leg objects in a List.

So I am doing the following everytime the user clicks the 'add a new leg' button:

// 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
When you say you "change the text of a textbox manually", do you mean typing something in the TextBox or setting SomeTextBox.Text = "SomeValue"? Because the 2nd way is overwriting the binding, so the TextBox.Text property is no longer bound. - Rachel
Are you also setting a binding in xaml? If so, it's possible that your xaml binding is overriding your custom binding. (depending on where the code above sits) - Matt Bridges
@Rachel: No, I am taking the first approach. Selecting the textbox with my cursor, writing some text inside it and then clicking another control so that the textbox looses its focus. - marc wellman
@Marc Your binding code works fine, so it has to be something to do with the way you're binding your data. Can you create a separate project and re-create a small sample that demonstrates the problem? - Rachel
@Marc Can you show the XAML of LegItem, particularly paxTextBox? - Rachel

1 Answers

1
votes

New Answer

Since you mentioned your binding was actually to a custom UserControl and not actually a TextBox, I would suggest looking into the XAML of your UserControl and making sure it is binding the data correctly


Old Answer

I did a quick test with a new Silverlight project and noticed that the startup project is SilverlightApplication1.Web, not SilverlightApplication.

This means that the breakpoint in the setter won't actually get hit when I run the project. You'll notice the breakpoint circle is just the outline, and the color isn't filled in. If you hover over it, it will say

The breakpoint will not currently be hit. No symbols have been loaded for this document

If I start SilverlightApplication1 instead of the .Web version, the breakpoint gets hit.

The property is getting changed correctly regardless of which version I startup, however the breakpoint isn't getting hit if I start the project with the .Web version. I suspect this is your issue.