2

I know there are many similar questions, I have read loads of them in the past day or so, but none of the solutions seem to help me.

I have a WPF user control, that is basically a souped-up ComboBox, on which I would like to enable data binding. I followed the code shown in the accepted answer to this SO question, but the binding isn't working.

A cut-down version of the content of the user control is as follows...

<UserControl x:Class="Sample.MyComboBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ComboBox Name="EntityTb"
              IsEditable="True" />
</UserControl>

There's obviously a lot more to it, but the rest isn't relevant to my question.

In the code-behind, I added a dependency property called Text as follows...

public static readonly DependencyProperty TextProperty
         = DependencyProperty.Register("Text", typeof(string),
  typeof(MyComboBox), new FrameworkPropertyMetadata() {
    BindsTwoWayByDefault = true,
    PropertyChangedCallback = TextChanged,
    DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
  });


private static void TextChanged(DependencyObject d,
                             DependencyPropertyChangedEventArgs e) {
  MyComboBox cmb = (MyComboBox)d;
  cmb.EntityTb.Text = e.NewValue.ToString();
}

public string Text {
  get => (string)GetValue(TextProperty);
  set => SetValue(TextProperty, value);
}

I then tried using this on a WPF window. The view model has a Customer property, which has a Name property which I want to bind to the custom control...

<controls:MyComboBox Grid.Column="1"
     Text="{Binding Customer.Name, Mode=TwoWay}" />

The Customer property is nothing more complex than...

private Customer _customer;

public Customer Customer {
  get => _customer;
  set {
    if (_customer != value) {
      _customer = value;
      RaisePropertyChanged();
    }
  }
}

...and the Customer type itself is just a plain C# class...

public partial class Customer {
  public string Name { get; set; }
}

However nothing happens. When the window loads, the customer name is not shown in the combobox, and if I type anything in there, the model is not updated.

I've done a lot of searching, and all code samples seem to look like the one above. Anyone able to tell me what I'm doing wrong?

6
  • Can you share the Customer class and most importantly the Name property inside it? Commented Mar 11, 2019 at 20:25
  • @Bijington Added some more. Thanks Commented Mar 11, 2019 at 20:32
  • Did you assign the view model instance to the Window's DataContext? And did you make sure that you did not set the UserControl's DataContext? Commented Mar 11, 2019 at 20:41
  • 1
    Also note that updating cmb.EntityTb.Text in a PropertyChangedCallback only works in one direction. Instead of the PropertyChangedCallback, better use a two-way binding like <ComboBox IsEditable="True" Text="{Binding Text, RelativeSource={RelativeSource AncestorType=UserControl}, Mode=TwoWay}"/> Commented Mar 11, 2019 at 20:48
  • @Clemens That last suggestion got me somewhere. The value now comes out of the view model and is set in the combobox, but if I change the combobox, the value isn't sent back to the view model. Any ideas? We're half-way there! Thanks Commented Mar 11, 2019 at 21:31

1 Answer 1

1

Updating cmb.EntityTb.Text in a PropertyChangedCallback only works in one direction.

Instead of that, use a two-way binding like

<ComboBox IsEditable="True"
    Text="{Binding Text, RelativeSource={RelativeSource AncestorType=UserControl}}"/>

As the ComboBox.Text property also binds two-way by default, setting Mode=TwoWay is redundant.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.