I have a WPF application that I try to code using MVVM.The goal is to make something like a notification center, that lists different types of data.
To do this, I want to fill a ListView on the main page with different ViewModels. One ViewModel for each type of data.
The problem is: When I put a (not a list) ViewModel in my ListView, it works fine. But if I put a list in my ListView, the program crashes on startup. I need the ListView to take a list (ObservableCollection perhaps) of mixed ViewModels.
I receive the error “Items collection must be empty before using ItemsSource.” at a seemingly random location in my code. Completely removing the code where the exception appears just causes it to show somewhere else.
I have the following:
C#:
public class MainViewModel : ObservableObject
{
private List<IPageViewModel> _items;
public MainViewModel()
{
_items = new List<IPageViewModel>
{
new StatusViewModel(),
new SettingsViewModel(),
new OverviewViewModel()
};
}
public List<IPageViewModel> Items => _items ?? (_items = newList<IPageViewModel>());
}
XAML:
<Window x:Class="InfoCenter.Views.Main.MainView"
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:test="clr-namespace:InfoCenter.Views.Test"
xmlns:main="clr-namespace:InfoCenter.Views.Main"
xmlns:views="clr-namespace:InfoCenter.Views"
xmlns:settings="clr-namespace:InfoCenter.Views.Settings"
xmlns:status="clr-namespace:InfoCenter.Views.Status"
xmlns:overview="clr-namespace:InfoCenter.Views.Overview"
mc:Ignorable="d"
Title="MainView" Height="450" Width="500"
MaxWidth="1920"
WindowStyle="None" Loaded="MainViewLoaded"
SizeChanged="MainViewSizeChanged"
PreviewKeyDown="OnPreviewKeyDown"
GotFocus="OnGotFocus"
Closing="OnClosing"
ResizeMode="NoResize"
d:DataContext="{d:DesignInstance main:MainViewModel}">
<Window.Resources>
<DataTemplate DataType="{x:Type overview:OverviewViewModel}">
<overview:OverviewView />
</DataTemplate>
<DataTemplate DataType="{x:Type status:StatusViewModel}">
<status:StatusView />
</DataTemplate>
<DataTemplate DataType="{x:Type settings:SettingsViewModel}">
<settings:SettingsView />
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="24" />
<RowDefinition Height="*" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="24" />
</Grid.ColumnDefinitions>
<Button Command="{Binding ButtonClickCommand}" CommandParameter="Minimize" Grid.Row="0" Grid.Column="1">
<Image Source="/Resources/arrow-down-1.png"></Image>
</Button>
<ListView ItemsSource="{Binding Items}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" ScrollViewer.HorizontalScrollBarVisibility="Hidden" PreviewMouseWheel="OnPreviewMouseWheel" ScrollViewer.VerticalScrollBarVisibility="Hidden">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="{Binding Path=Items.Header}" />
<ContentControl Grid.Row="1" Grid.Column="0" Content="{Binding}" />
</Grid>
</ListView>
<StatusBar FlowDirection="RightToLeft" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2">
<Image Width="24" Height="24" Source="{Binding ConnectionIcon}" />
</StatusBar>
</Grid>
</Window>
I really hope that you can help. I have been trying to fix it the whole day!