bruce.wins
bruce.wins

Reputation: 92

Binding Element to Property from Inherited Data Context

I have a WPF control pane with sixteen of the same child control containing a combobox that needs to be bound to a list in the Parent Control code behind. I was really struggling to get this list to bind until I found this: Binding objects defined in code-behind.

Setting DataContext="{Binding RelativeSource={RelativeSource Self}}" on the Parent Control allowed me to bind the combobox on the child control directly.

The problem is that now I want to create a Data Template to display the list items properly, but nothing I put in the Binding or Relative Source Displays anything.

ControlPane.xaml

<UserControl
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         x:Class="ControlPane"
         x:Name="CtrlPaneWpf"
         DataContext="{Binding RelativeSource={RelativeSource Self}}"
         > 

ControlPane.xaml.cs

public class TwoStringClass
{
    public string string1;
    public string colorHex;
}

public ObservableCollection<TwoStringClass> TwoStringClass1
{
    get
    {
        ObservableCollection<TwoStringClass> cmbclrs = new ObservableCollection<TwoStringClass>();
        cmbclrs.Add(new TwoStringClass() { string1 = "This", colorHex = "#FF0000" });
        cmbclrs.Add(new TwoStringClass() { string1 = "That", colorHex = "#FF352E2"  });
        cmbclrs.Add(new TwoStringClass() { string1 = "The Other", colorHex = "#FFF4F612"  });
        return cmbclrs;
    }    
}

ChildControl.xaml

<UserControl
            x:Name="ChildControl"
            >
            <ComboBox x:Name="cmbFontColor" ItemsSource="{Binding TwoStringClass1}" >
                <ComboBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <TextBlock Text="{Binding string1}"  />
                            <Rectangle Fill="{Binding colorHex}" />
                        </StackPanel>
                    </DataTemplate>
                </ComboBox.ItemTemplate>
            </ComboBox>
</UserControl>

I know the Binding is Working because I get the correct number of (blank) items in the Combobox and can see the class name if I remove the ItemTemplate.

I can't figure out for the life of me why binding to the property name isn't working here as it does when the list comes from a control's own code behind.

There must be some other information I need to add to the TextBlock binding, but no matter what DataContext or RelativeSource I try, I always get blank items.

Upvotes: 1

Views: 860

Answers (2)

Bobby
Bobby

Reputation: 487

I believe the answer to your question is the same as the answer to a question I posted recently, which was answered by StewBob. Here is my slightly modified version of his answer, which should also fix the issue you are having.

You can see my original thread here: WPF ListBox with CheckBox data template - Binding Content property of Checkbox not working

I see you added "This", "That", and "The Other" as your data source, presumably for simplicity in posting this question to SO. Please be aware that if your true underlying data source can change, when doing DataBinding, your class needs to implement INotifyPropertyChanged for the data to properly display in the UI. An example:

public class TwoStringClass: INotifyPropertyChanged
{

  private string _String1;
  private string _ColorHex;

  public string String1
  {
    get
    {
      return _String1;
    }
    set
    {
      if (value != _String1)
      {
        _String1 = value;
        NotifyPropertyChanged("String1");
      }
    }
  }

  public string ColorHex
  {
    get
    {
      return _ColorHex;
    }
    set
    {
      if (value != _ColorHex)
      {
        _ColorHex = value;
        NotifyPropertyChanged("ColorHex");
      }
    }
  }

  private void NotifyPropertyChanged(string info)
  {
    if (PropertyChanged != null)
    {
      PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;
}

This shows the class, two properties, and the needed event and method for implementing INotifyPropertyChanged.

Upvotes: 0

Clemens
Clemens

Reputation: 128060

Data binding in WPF works with public properties only, not with fields. Your item class should look like this:

public class TwoStringClass
{
    public string string1 { get; set; }
    public string colorHex { get; set; }
}

That said, there are widely accepted naming convention, according to which you should use Pascal case for property names, e.g. String1 and ColorHex.

Upvotes: 1

Related Questions