绑定到 ItemsControl 仅适用于代码隐藏

Binding to ItemsControl only works in code behind

我正在尝试将 ObservableCollection 绑定到 ItemsControl。我创建了一个名为 Persons 的 class,它具有一些属性。然后我创建了一个 ObservableCollection 并在其中添加了一些 Persons。

如果我给 ItemsControl 一个 x:Name="PersonHolder" 并添加带有 PersonHolder.ItemsSource = persons 的 ItemsSource,那么一切正常。但是,如果我试图在 XAML 中添加具有绑定的人员...没有结果。

这里是 XAML:

<StackPanel Background="White">
    <ItemsControl ItemsSource="{Binding persons}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</StackPanel>

一些来自 C# 的代码

public ObservableCollection<Person> persons { get; set; }
public MainWindow()
{
    InitializeComponent();
    persons = new ObservableCollection<Person>();
    persons.Add(new Person { Name = "Peter" });
}

public class Person
{
    public string Name { get; set; }
}

希望你能帮助我。

此致。

您必须将其绑定到控件本身:

 <ItemsControl ItemsSource="{Binding persons,  
               RelativeSource={RelativeSource AncestorType={x:Type Window}}}">

否则它会立即绑定到已设置为 null 的 DataContext 属性。你也可以在后面的代码中设置DataContext,比如DataContext = this.

所有绑定错误都在 "Output" window.

默认情况下,绑定将在当前 DataContext 中搜索 属性。您需要设置绑定上下文,例如通过在代码中手动设置 DataContext。但是,由于 persons 不会引发 PropertyChanged 事件,因此您需要在创建 persons 之后设置 DataContext ,否则 UI 将不会收到 属性 的通知已经改变

InitializeComponent();
persons = new ObservableCollection<Person>();
//after persons is created
DataContext = this;

无需实施 INotifyPropertyChanged,并将其保留在 XAML 中,您可以保留 persons

的单个实例
private readonly ObservableCollection<Person> _persons = new ObservableCollection<Person>();

public ObservableCollection<Person> persons { get { return _persons; } }

public MainWindow()
{
    InitializeComponent();      
    persons.Add(new Person { Name = "Peter" });
}

并在 XAML

<Window ... x:Name="window">
    <!-- .... -->
    <ItemsControl ... ItemsSource="{Binding ElementName=window, Path=persons}">

我宁愿建议以下实现。

Window:

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();
        var context = new SomeContext();
        DataContext = context;
        context.AddPerson();
    }
}

上下文:

public class SomeContext 
{
    public ObservableCollection<Person> People { get; set; }

    public SomeContext()
    {
        People = new ObservableCollection<Person>();
        People.Add(new Person { Name = "Samuel" });
    }

    public void AddPerson()
    {
        People.Add(new Person { Name = "Peter" });
    }
}

public class Person
{
    public string Name { get; set; }
} 

XAML:

<Window x:Class="BindingTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel Background="White">
            <ItemsControl ItemsSource="{Binding People}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Name}" />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </StackPanel>
    </Grid>
</Window>