将继承数据上下文中的元素绑定到 属性

Binding Element to Property from Inherited Data Context

我有一个 WPF 控制窗格,其中包含 16 个相同的子控件,其中包含一个组合框,需要绑定到后面的父控件代码中的列表。我真的很难让这个列表绑定,直到我发现这个:Binding objects defined in code-behind

在父控件上设置 DataContext="{Binding RelativeSource={RelativeSource Self}}" 允许我直接在子控件上绑定组合框。

问题是现在我想创建一个数据模板来正确显示列表项,但是我在绑定或相对源中没有显示任何内容。

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>

我知道绑定正在工作,因为我在组合框中获得了正确数量的(空白)项目,并且如果我删除 ItemTemplate 可以看到 class 名称。

我一辈子都弄不明白为什么绑定到 属性 名称在这里不起作用,因为它在列表来自控件自己的代码后面时起作用。

我一定有一些其他信息需要添加到 TextBlock 绑定中,但无论我尝试什么 DataContext 或 RelativeSource,我总是得到空白项。

WPF 中的数据绑定仅适用于 public 属性,不适用于字段。您的商品 class 应如下所示:

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

也就是说,有广泛接受的命名约定,根据该约定,您应该使用 Pascal case 作为 属性 名称,例如String1ColorHex.

我相信您的问题的答案与我最近发布的一个问题的答案相同,该问题由 StewBob 回答。这是我对他的回答稍作修改的版本,它也应该可以解决您遇到的问题。

你可以在这里看到我的原始线程:

我看到您添加了 "This"、"That" 和 "The Other" 作为您的数据源,大概是为了简单地将此问题发布到 SO。请注意,如果您真正的基础数据源可以更改,则在执行 DataBinding 时,您的 class 需要实施 INotifyPropertyChanged 以使数据在 UI 中正确显示。一个例子:

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

这显示了 class、两个属性以及实现 INotifyPropertyChanged 所需的事件和方法。