WPF - 在ListView的ItemsSource中绑定不能是列表

WPF - 在ListView的ItemsSource中绑定不能是列表

问题描述:

我有一个WPF应用程序,我尝试使用MVVM进行编码。目标是制作类似于通知中心的东西,列出不同类型的数据。WPF - 在ListView的ItemsSource中绑定不能是列表

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

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

我在我的代码中看似随机的位置收到错误“Item 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> 

我真的希望你能有所帮助。我一直在努力解决这一整天!

你已经把一件事ListView内容在这里:A 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是一个列表,它没有Header属性。 IPageViewModelHeader属性吗?目前,我会假设情况是这样的;让我知道,如果我错了。

<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

是的,IPageViewModel有一个Header属性,我想用网格以某种方式显示项目。 Your ItemTemplate解决方案完成了这项工作。非常感谢你! – Niksen

基于我建议改变你的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> 

希望这会有所帮助!