jeromej
jeromej

Reputation: 11578

CodeBehind TextBox Binding

My goal was to replace <TextBox Text={Binding TopTextContent} /> (which works as is) in the xaml view with this in the code behind:

  public partial class MyView: UserControl
  {
    public MyView()
    {
      InitializeComponent();

      // Supposed to replace: // <TextBox Text={Binding TopTextContent} />
      InputContextMenu("Top Text", "TopTextContent");
    }

    private void InputContextMenu([NotNull] string header, [NotNull] string propName)
    {
      var textBox = new TextBox
      {
        MaxLength = 12,
        Width = 80,
        FocusVisualStyle = null
      };

      textBox.SetBinding(
        TextBox.TextProperty, 
        new Binding
        {
          Path = new PropertyPath(propName),
          Source = DataContext, // (MyView)DataContext didn't work as well
          Mode = BindingMode.TwoWay
        }
      );

      CodeBehindTextInputs.Items.Add(
        new MenuItem
        {
          Header = header,
          Focusable = false,
          Items = {textBox}
        }
      );
    }
  }

Afaik it should work but it doesn't, the field does appear but the input field is empty and modifying it doesn't modify the value it is supposed to be binded to.

Snoop shows it in red:

showcasing that snoop does show {Path=TopTextContent} but in red

I'm not sure how to further debug it or what I'm doing wrong.

Upvotes: 0

Views: 252

Answers (2)

Clemens
Clemens

Reputation: 128062

Do not explicitly set the Binding's Source. The Binding will automatically use the TextBox's DataContext as source object - which inherits its value from its parent view element - even when it is set later:

textBox.SetBinding(
    TextBox.TextProperty, 
    new Binding
    {
        Path = new PropertyPath(propName),
        Mode = BindingMode.TwoWay
    });

Upvotes: 1

jeromej
jeromej

Reputation: 11578

I'm not fully understanding it all yet but it would seem that my DataContext does get populated AFTER the constructor (so it was still null).

I solved it by resorting to the DataContextChanged event:

public SpecificInformationView()
{
  InitializeComponent();

  DataContextChanged += OnDataContext;
}

private void OnDataContext(object sender, DependencyPropertyChangedEventArgs e)
{
  InputContextMenu("Top Text", "TopTextContent");
}

Upvotes: 0

Related Questions