【问题标题】:Binding to ItemsControl only works in code behind绑定到 ItemsControl 仅适用于后面的代码
【发布时间】:2015-03-15 05:37:18
【问题描述】:

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

如果我给 ItemsControl 一个 x:Name="PersonH​​older" 并将 ItemsSource 添加到 PersonH​​older.ItemsSource = people 那么一切正常。但是,如果我尝试在 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; }
}

希望你能帮助我。

最好的问候。

【问题讨论】:

  • Control的DataContext在哪里设置?

标签: c# wpf xaml binding observablecollection


【解决方案1】:

您必须将它与控件本身绑定:

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

否则,它会绑定到现在已设置为 null 的 DataContext 属性。您也可以在后面的代码中设置DataContext,例如DataContext = this

所有绑定错误都在“输出”窗口中。

【讨论】:

  • 该代码正确吗? RelativeSource 绑定到 Self 不会在 ItemsControl 而不是 Window 上寻找名为 persons 的属性吗?
  • XAML 的工作原理,但我不明白为什么我需要将 RelativeSource 带到我的框架/表单。
【解决方案2】:

默认情况下,绑定将在当前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}">

【讨论】:

  • 这行得通,但我不想让这段代码落后,我想按照 XAML 做这些事情。问候
  • 我愿意。但是 ObservableCollection 有 INotifyPropertyChanged 我虽然。所以如果我在那里改变一个项目,它应该在视图中改变。还是不行?
  • ObservableCollection 同时实现 INotifyPropertyChangedINotifyCollectionChanged 这意味着如果集合中的项目更改 UI 将被通知但 MainWindow 不实现 INotifyPropertyChangedpersons 属性不引发PropertyChanged 事件,因此无法更改。长话短说集合项目可以更改,但集合本身不能更改(即不实现INotifyPropertyChanged
  • 所以如果我设置“DataContext = this”,我可以在其他元素上创建更多绑定而不更改任何内容,或者我需要再次设置“DataContext = this”?
  • 当您这样做时,MainWindow 将成为您的 DataContext 和 MainWindow 子绑定的默认绑定上下文。
【解决方案3】:

我宁愿建议以下实现。

窗口:

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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-08
    • 2018-11-24
    • 2011-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-19
    • 1970-01-01
    相关资源
    最近更新 更多