I am trying to bind a 2D array of buttons arranged in stackpanels to a 2D ObservableCollection…
Yet, I’m afraid I don’t understand something very elementary about binding.
My XAML:
<Window.Resources>
<DataTemplate x:Key="ItemsAsButtons">
<Button Content="{Binding}" Height="100" Width="100"/>
</DataTemplate>
<DataTemplate x:Key="PanelOfPanels">
<ItemsControl ItemsSource="{Binding Path=DayNumbers}" ItemTemplate=" {DynamicResource ItemsAsButtons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DataTemplate>
</Window.Resources>
...
<ItemsControl x:Name="DaysPanel" Grid.ColumnSpan="7" Grid.Row="2"
ItemTemplate="{DynamicResource PanelOfPanels}"/>
My C# code:
The backend:
/// <summary>
/// Window BE for Calendar.xaml
/// </summary>
public partial class Calendar : Window
{
private CalendarViewModel _vm;
public Calendar()
{
InitializeComponent();
_vm = new CalendarViewModel();
this.DataContext = _vm;
}
}
The ViewModel:
class CalendarViewModel
{
CalendarMonth _displayedMonth;
EventCalendar _calendar;
public CalendarViewModel()
{
_displayedMonth = new CalendarMonth();
}
public ObservableCollection<ObservableCollection<int>> DayNumbers
{
get
{
return _displayedMonth.DayNumbers;
}
}
}
I’m trying to populate the buttons with values from CalendarViewModel.DayNumbers – yet the buttons do not appear. I’m clearly doing something wrong with my binding.
Like Igor said, you need specify
ItemsSource={Binding DayNumbers}in outer-mostItemsControl, otherwise, it binds to theDataContext, which isCalendarViewModeland it is notIEnumerable.Once you do that, it will apply
<DataTemplate x:Key="PanelOfPanels">for each item insideDayNumbers. Note that theDataContextof theDataTemplatein each element inDayNumbers, which is of typeObservableCollection<int>. Here you cannot specifyItemsSource="{Binding Path=DayNumbers}"asDayNumbersis not a valid property inObservableCollection<int>. Instead, sinceObservableCollection<int>is already aIEnumerable, it should be fine not specifyingItemsSourcesince it will by default bind toDataContext.Finally, it goes to your inner-most
<DataTemplate x:Key="ItemsAsButtons">, and you can put button there as what you did.Hope it clarifies a little bit. Sorry I don’t have the environment to test it out and give you the solution.
Debugging WPF bindings is not straightforward. One tip is you can use dummy converter and set breakpoint in the
Convertmethod to see what it binds.