WPF - ListView的ItemsSource中的绑定不能是List

时间:2017-10-12 12:47:43

标签: c# wpf listview mvvm data-binding

我有一个WPF应用程序,我尝试使用MVVM进行编码。目标是制作类似于通知中心的内容,列出不同类型的数据。

为此,我想在主页面上使用不同的ViewModel填充ListView。每种类型的数据都有一个ViewModel。

问题是: 当我在ListView中放入一个(不是列表)ViewModel时,它工作正常。但是如果我在ListView中放置一个列表,程序会在启动时崩溃。我需要ListView来获取混合ViewModel的列表(可能是ObservableCollection)。

我在代码中看似随机的位置收到错误“Items collection必须为空,然后才使用ItemsSource。”。完全删除出现异常的代码只会使其显示在其他地方。

我有以下内容:

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>

我真的希望你能提供帮助。我一整天都试图解决它!

2 个答案:

答案 0 :(得分:2)

您已将{em>一件事放在ListView内容中:Grid控件。不要那样做。有两种方法可以在XAML中填充ListView:绑定ItemsSource 将项目放在ListView元素的内容中。你不能同时做到这两件事,而且你做了两件事,所以它引发了一个例外。

这是ItemsSource版本。

<ListView 
    ItemsSource="{Binding Items}" 
    Grid.Row="1" 
    Grid.Column="0" 
    Grid.ColumnSpan="2" 
    ScrollViewer.HorizontalScrollBarVisibility="Hidden" 
    PreviewMouseWheel="OnPreviewMouseWheel" 
    ScrollViewer.VerticalScrollBarVisibility="Hidden"
    />

我不确定Grid是什么意思;你可能必须找到其他地方才能把它。

但我的猜测是希望它用于显示项目。我们可以通过将其变为ItemTemplate来实现这一目标。不过我对它有点困惑:什么是Items.HeaderItems是一个List,没有Header属性。 IPageViewModel是否有Header属性?目前我会认为是这样的;如果我弄错了,请告诉我。

<ListView 
    ItemsSource="{Binding Items}" 
    Grid.Row="1" 
    Grid.Column="0" 
    Grid.ColumnSpan="2" 
    ScrollViewer.HorizontalScrollBarVisibility="Hidden" 
    PreviewMouseWheel="OnPreviewMouseWheel" 
    ScrollViewer.VerticalScrollBarVisibility="Hidden"
    >
    <ListView.ItemTemplate>
        <DataTemplate>
            <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 Header}" 
                    />
                <ContentControl 
                    Grid.Row="1" 
                    Grid.Column="0" 
                    Content="{Binding}" 
                    />
            </Grid>
        <DataTemplate>
    </ListView.ItemTemplate>
</ListView>

答案 1 :(得分:0)

根据错误,我建议更改您的XAML,如前面"Items collection must be empty before using ItemsSource."中所述

试试这个XAML:

     <ListView ItemsSource="{Binding Items}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" ScrollViewer.HorizontalScrollBarVisibility="Hidden" PreviewMouseWheel="OnPreviewMouseWheel" ScrollViewer.VerticalScrollBarVisibility="Hidden">
         <ListView.View>
            <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.View>
     </ListView>

希望它会有所帮助!