【问题标题】:WPF - Binding in ListView's ItemsSource cannot be a ListWPF - ListView 的 ItemsSource 中的绑定不能是列表
【发布时间】:2018-03-24 09:58:04
【问题描述】:

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

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

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

我收到错误消息“在使用 ItemsSource 之前,Items 集合必须为空。”在我的代码中看似随机的位置。完全删除出现异常的代码只会导致它显示在其他地方。

我有以下几点:

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>

我真的希望你能提供帮助。我整天都在努力修复它!

【问题讨论】:

    标签: c# wpf listview mvvm data-binding


    【解决方案1】:

    您已经在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.Header 是什么? Items 是一个列表,它没有 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>
    

    【讨论】:

    • 是的,IPageViewModel 有一个 Header 属性,我想使用网格以某种方式显示项目。您的 ItemTemplate 解决方案完成了这项工作。非常感谢!
    【解决方案2】:

    基于错误,我建议更改您的 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>
    

    希望对您有所帮助!

    【讨论】:

    • 这不是有效的 XML。
    猜你喜欢
    • 2014-12-08
    • 2011-01-14
    • 2020-05-17
    • 1970-01-01
    • 2011-03-16
    • 2013-01-14
    • 1970-01-01
    • 2015-04-07
    • 1970-01-01
    相关资源
    最近更新 更多