wpfdata-binding

I do not understand error message 'Binding cannot be changed after is has been used.'


I have 2 textboxes that I need to find in a WPF grid. I've found both of them. I then bind the the textboxes to properties in a class that uses INotifyPropertyChanged. The first textbox binds correctly. The second does not. I tried creating a new second text box and binding it to the original 2nd textbox property. I now receive error 'Binding cannot be changed after it has been used'. I tried clearing the binding using 'BindingOperations.ClearAllBindings(textBox02)' but still get the error. I deleted the 2nd textbox and created another. It ran once without the error and then the error reappeared. How to add IValueConverter to an existing Binding has the same problem. I tried creating a new binding but get the same error on 2nd run. I'm very new to WFP. I don't know if the error is telling me that I need to use a new binding, bind to a different property, or replace the textbox. I've tried all three and still have the problem. Code for the various areas are below.
Thanks in advance,

Rod McKay

Create the textboxes:

                chartTraderCustomTextBlockArray[1] = new TextBlock()
                {
                    FontFamily = ChartControl.Properties.LabelFont.Family,
                    FontSize = 13,
                    Foreground = ChartControl.Properties.ChartText,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    Margin = new Thickness(5, 20, 5, 5),
                    Name = "txtBlock01",
                    Text = string.Format("{0} ", indicatorRiskValue)
                };

                chartTraderCustomTextBoxArray[0] = new TextBox()
                {
                    FontFamily = ChartControl.Properties.LabelFont.Family,
                    FontSize = 13,
                    Foreground = ChartControl.Properties.ChartText,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    Margin = new Thickness(5, 5, 5, 5),
                    Name = "textBox02",
                    Text = string.Format("{0} ", shareQuantity),
                    Height = 20,
                    Width = 240
                };

I used the following code to find the text boxes:

chartWindow = System.Windows.Window.GetWindow(e.Parent) as NinjaTrader.Gui.Chart.Chart;
chartTraderGrid = (chartWindow.FindFirst("ChartWindowChartTraderControl") as ChartTrader).Content as Grid;
textBox00 = chartTraderGrid.FindFirst("TextBox00") as System.Windows.Controls.TextBox;
textBox02 = chartTraderGrid.FindFirst("TextBox02") as System.Windows.Controls.TextBox;

The boxes are found correctly. I next bind the textboxes to properties in a class that uses INotifyPropertyChanged

Binding binding = new Binding("Quantity");
binding.Source = noOfShares;
textBox00.SetBinding(TextBox.TextProperty, binding)
Binding binding2 = new Binding("Risk");
binding.Source = noOfShares;
textBox02.SetBinding(TextBox.TextProperty, binding2);

This is the binding source:

public class NumberOfShares : ObservableObject
{
    private string _risk;
    private string _quantity;
    // Declare the event
    public event PropertyChangedEventHandler PropertyChanged;
    public NumberOfShares()
    {
    }
    public string Risk
    {
        get { return _risk; }
        set
        {
            _risk = value;
            OnPropertyChanged();
        }
    }

    public string Quantity
    {
        get { return _quantity; }
        set
        {
            _quantity = value;
               // Call OnPropertyChanged whenever the property is updated
            OnPropertyChanged();
        }
    }

    // Create the OnPropertyChanged method to raise the event
    // The calling member's name will be used as the parameter.
    protected void OnPropertyChanged([CallerMemberName] string quantity = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(quantity));
    }
}

public class ObservableObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string propertyname = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
    }

}


Solution

  • I think you just have a random typing error. Correct would be:

    Binding binding = new Binding("Quantity");
    binding.Source = noOfShares;
    textBox00.SetBinding(TextBox.TextProperty, binding)
    Binding binding2 = new Binding("Risk");
    // binding.Source = noOfShares; Invalid line
    binding2.Source = noOfShares; // Correct variant
    textBox02.SetBinding(TextBox.TextProperty, binding2);
    

    In order to avoid this kind or error, use initializers:

    Binding binding = new Binding("Quantity")
    {
        Source = noOfShares
    };
    textBox00.SetBinding(TextBox.TextProperty, binding)
    
    Binding binding2 = new Binding("Risk")
    {
        Source = noOfShares
    };
    textBox02.SetBinding(TextBox.TextProperty, binding2);