I've run into an issue that I think may be a WPF bug. I've got a WPF view that contains two ItemsControl elements that have their ItemsSource properties both bound to the same ObservableCollection property on the ViewModel. The behavior I'm seeing is that only the ItemsControl declared last in the XAML is rendering its content properly.
My View consists of the following:
<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>
You can see I've simply got a grid with a textblock and two ItemsControls - each bound to the same property on the ViewModel.
The code-behind of the View is pretty straight-forward: using System.Windows; using ItemsControlBindingTest.ViewModels;
namespace ItemsControlBindingTest.Views
{
/// <summary>
/// Interaction logic for ItemsControlBindingTestView.xaml
/// </summary>
public partial class ItemsControlBindingTestView : Window
{
public ItemsControlBindingTestView()
{
InitializeComponent();
DataContext = new ItemsControlBindingTestViewModel();
}
}
}
You can see I'm simply setting my View's DataContext property to a new instance of the ItemsControlBindingTestViewModel.
And the code for the 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);
}
}
}
All we're doing here is adding three buttons to the ButtonList property.
Now, when I display this View, I only see the buttons rendered in the ItemsControl that is declared last in the XAML:
If I switch the assigned column values on my two ItemsControls:
<ItemsControl Grid.Column="1" Grid.Row="1" ItemsSource="{Binding ButtonList}"/>
<ItemsControl Grid.Column="0" Grid.Row="1" ItemsSource="{Binding ButtonList}"/>
Then the ItemsControl in column 0 (on the left) will render the content, and the ItemsControl on the right will remain blank:
Looking at the elements in Snoop yields some interesting information:
Both ItemsControls' ItemsSource properties correctly reflect a binding to the ButtonList.
In fact, I can delve into this ItemsSource and see the three buttons in ButtonList:
The last-declared ItemsControl also shows a valid ItemsSource property:
And I can delve into this ItemsSource as well and see the three buttons in ButtonList:
Snoop also shows the last-declared ItemsControl's StackPanel has children:
While the first-declared ItemsControl's StackPanel has no children:
Am I missing something here, or is this a bug in WPF?