无法将ItemsSource绑定到ElementName

时间:2017-02-02 16:00:53

标签: c# wpf binding

这可能是一个愚蠢的问题,但我不能用ItemsSource工作做一个简单的例子。我的XAML:

<Window x:Class="TestDataGrid.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"
        xmlns:local="clr-namespace:TestDataGrid"
        mc:Ignorable="d" Height="250" Width="300" Name="MyWindow">
    <ListBox ItemsSource="{Binding MyItems, ElementName=MyWindow}" Background="{Binding MyBrush, ElementName=MyWindow}"/>
</Window>

代码:

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    private ObservableCollection<Item> items;

    public MainWindow()
    {
        InitializeComponent();
        items = new ObservableCollection<Item>();
        items.Add(new Item { Key = "Key1", Value = "Value1" });
        items.Add(new Item { Key = "Key2", Value = "Value2" });
        items.Add(new Item { Key = "Key3", Value = "Value3" });
    }

    public ObservableCollection<Item> MyItems
    {
        get { return items; }
    }

    public Brush MyBrush
    {
        get { return Brushes.LightPink; }
    }
}

public class Item
{
    public string Key { get; set; }
    public string Value { get; set; }
}

如果我在代码中设置ItemsSource,或者如果我设置DataContext=this然后从我的绑定中删除ElementName,它就有效。但为什么它不能与ElementName一起使用? 我可以像这样绑定背景颜色,但不能绑定。

我知道如何使用DataContext或代码隐藏,但我很感兴趣为什么这个特定的例子不起作用,我错过了什么?

2 个答案:

答案 0 :(得分:2)

  

我知道如何使用DataContext或代码隐藏,但我很感兴趣为什么这个特定的例子不起作用,我错过了什么?

正如@Clemens所指出的那样,如果在调用InitializeComponent()之前填充源集合,则绑定实际上会起作用。

在代码中设置DataContext和在XAML中创建ElementName绑定之间的区别在于后者已在[PIDinRootline = 40] plugin.tx_cal_controller.view.list.listTemplate = fileadmin/Templates/Html/ExtCal/list_aktuell.tmpl [GLOBAL] 调用期间建立。稍后添加的项目 - 未实现InitializeComponent的集合 - 将被忽略。

INotifyCollectionChanged

你也可以使用RelativeSource绑定到父窗口,这可以:

public MainWindow()
{
    items = new ObservableCollection<Item>();
    items.Add(new Item { Key = "Key1", Value = "Value1" });
    items.Add(new Item { Key = "Key2", Value = "Value2" });
    items.Add(new Item { Key = "Key3", Value = "Value3" });
    InitializeComponent();
}

答案 1 :(得分:1)

您在初始化Windows后设置了MyItems,并且由于示例中的MyItems没有实现setter和INotifyPropertyChanged方式,因此您的UI线程永远不会因为您的更改而发出警告在你的收藏品上制作。

您可以设置以下两种解决方案:

解决方案1 ​​

直接在get:

中实例化您的Observable集合
public ObservableCollection<Item> MyItems {
        get {
            var _items = new ObservableCollection<Item>();
            _items.Add(new Item { Key = "Key1", Value = "Value1" });
            _items.Add(new Item { Key = "Key2", Value = "Value2" });
            _items.Add(new Item { Key = "Key3", Value = "Value3" });
            return _items;
        }
    }

解决方案2

使用INotifyPropertyChanged界面:

当您设置项目时,您的UI线程知道在xaml部分中有更改要做

public partial class MainWindow : Window, INotifyPropertyChanged {
    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    private ObservableCollection<Item> _items;
    public ObservableCollection<Item> MyItems {
        get { return _items; }
        set {
            _items = value;
            PropertyChanged(this, new PropertyChangedEventArgs(nameof(MyItems)));
        }
    }

    public MainWindow () {
        InitializeComponent();
        MyItems = new ObservableCollection<Item>();
        MyItems.Add(new Item { Key = "Key1", Value = "Value1" });
        MyItems.Add(new Item { Key = "Key2", Value = "Value2" });
        MyItems.Add(new Item { Key = "Key3", Value = "Value3" });
    }

....