【发布时间】:2014-01-30 01:02:56
【问题描述】:
我遇到了一个我认为可能是 WPF 错误的问题。我有一个 WPF 视图,其中包含两个 ItemsControl 元素,它们的 ItemsSource 属性都绑定到 ViewModel 上的同一个 ObservableCollection 属性。我看到的行为是只有在 XAML 中最后声明的 ItemsControl 才能正确呈现其内容。
我的视图包含以下内容:
<Window x:Class="ItemsControlBindingTest.Views.ItemsControlBindingTestView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ItemsControlBindingTestView" Height="300" Width="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="2" TextWrapping="Wrap">
Note that of the two ItemsControls in this view, only the last declared in XAML renders its contents properly.
</TextBlock>
<ItemsControl Grid.Column="0" Grid.Row="1" ItemsSource="{Binding ButtonList}"/>
<ItemsControl Grid.Column="1" Grid.Row="1" ItemsSource="{Binding ButtonList}"/>
</Grid>
</Window>
您可以看到我只是得到了一个带有文本块和两个 ItemsControl 的网格 - 每个都绑定到 ViewModel 上的相同属性。
View 的代码隐藏非常简单: 使用 System.Windows; 使用 ItemsControlBindingTest.ViewModels;
namespace ItemsControlBindingTest.Views
{
/// <summary>
/// Interaction logic for ItemsControlBindingTestView.xaml
/// </summary>
public partial class ItemsControlBindingTestView : Window
{
public ItemsControlBindingTestView()
{
InitializeComponent();
DataContext = new ItemsControlBindingTestViewModel();
}
}
}
您可以看到我只是将 View 的 DataContext 属性设置为 ItemsControlBindingTestViewModel 的新实例。
还有 ItemsControlBindingTestViewModel 的代码:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Controls;
namespace ItemsControlBindingTest.ViewModels
{
public class ItemsControlBindingTestViewModel : MVVM.ViewModelBase
{
private ObservableCollection<Button> buttonList;
public ObservableCollection<Button> ButtonList
{
get { return buttonList; }
set
{
buttonList = value;
NotifyPropertyChanged(() => ButtonList);
}
}
public ItemsControlBindingTestViewModel()
{
List<Button> tempList = new List<Button>();
tempList.Add(new Button { Content = "Button 1" });
tempList.Add(new Button { Content = "Button 2" });
tempList.Add(new Button { Content = "Button 3" });
ButtonList = new ObservableCollection<Button>(tempList);
}
}
}
我们在这里所做的只是向 ButtonList 属性添加三个按钮。
现在,当我显示此视图时,我只看到在 XAML 中最后声明的 ItemsControl 中呈现的按钮:
如果我在两个 ItemsControls 上切换分配的列值:
<ItemsControl Grid.Column="1" Grid.Row="1" ItemsSource="{Binding ButtonList}"/>
<ItemsControl Grid.Column="0" Grid.Row="1" ItemsSource="{Binding ButtonList}"/>
那么第0列(左边)的ItemsControl会渲染内容,右边的ItemsControl会保持空白:
查看 Snoop 中的元素会产生一些有趣的信息:
ItemsControls 的 ItemsSource 属性都正确反映了与 ButtonList 的绑定。
其实我可以深入研究这个ItemsSource,看到ButtonList中的三个按钮:
最后声明的 ItemsControl 还显示了一个有效的 ItemsSource 属性:
我也可以深入研究这个 ItemsSource 并查看 ButtonList 中的三个按钮:
Snoop 还显示最后声明的 ItemsControl 的 StackPanel 有子项:
虽然第一个声明的 ItemsControl 的 StackPanel 没有子级:
我在这里遗漏了什么,还是这是 WPF 中的错误?
【问题讨论】: