You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF ListView绑定自定义集合无数据显示问题求助

问题描述

用户的WPF ListView绑定ViewModel的ObservableCollection<Player>后无数据显示,相关代码如下:

XAML代码

<ListView x:Name="listviewPlayers"  ItemsSource="{Binding Players}" Height="200">
    <ListView.View>
        <GridView>
            <GridViewColumn Width="235">
                <GridViewColumn.Header>
                    <Label Grid.Column="2" Content ="Name" Foreground="Black" FontSize="10"></Label>
                </GridViewColumn.Header>
            </GridViewColumn>
            <GridViewColumn Width="235">
                <GridViewColumn.Header>
                    <Label Grid.Column="1" Content ="Score" Foreground="Black" FontSize="10"></Label>
                </GridViewColumn.Header>
            </GridViewColumn>
            <GridViewColumn Width="235">
                <GridViewColumn.Header>
                    <Label Grid.Column="0" Content ="Games" Foreground="Black" FontSize="10"></Label>
                </GridViewColumn.Header>
            </GridViewColumn>
        </GridView>
    </ListView.View>
    <ListView.ItemTemplate>
        <DataTemplate DataType="local:MainPageViewModel">
            <Grid Height="25">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <Label Content="{Binding Name}" FontWeight="Bold" FontSize="10" Foreground="Black">
                </Label>
                <Label Grid.Column="1" Content="{Binding CurrentScore}" FontSize="10" HorizontalContentAlignment="Center" Foreground="Black">
                </Label>
                <Label Grid.Column="2" Content="{Binding GamesWon}" HorizontalContentAlignment="Center" FontSize="10" Foreground="Black">
                </Label>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

ViewModel代码

public ObservableCollection<Player> Players
{
    get { return players; }
    set
    {
        players = value;
        foreach (Player p in players)
        {
            PlayerNames.Add(p.Name);
        }
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Players"));
    }
}

Player实体类

public class Player : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    private string name = "";
    public string Name
    {
        get { return name; }
        set { name = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name")); }
    }

    private string currentScore = "0";
    public string CurrentScore
    {
        get { return currentScore; }
        set
        {
            currentScore = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentScore"));
        }
    }

    private string gamesWon = "0";
    public string GamesWon
    {
        get { return gamesWon; }
        set { gamesWon = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("GamesWon")); }
    }
}

用户已设置设计时DataContext:

d:DataContext="{d:DesignInstance Type=local:MainPageViewModel}"
问题分析与解决建议

1. DataTemplate的DataType错误

ListView的ItemsSource绑定的是Players(ObservableCollection<Player>),每个列表项的数据上下文是Player对象,而非MainPageViewModel。但你把DataTemplate的DataType设为了local:MainPageViewModel,导致绑定无法匹配Player的属性。

修正:将DataTemplate的DataType改为local:Player:

<DataTemplate DataType="local:Player">

2. GridView与ItemTemplate冲突

当ListView使用ListView.View指定GridView时,全局的ItemTemplate会被忽略。GridView需要通过DisplayMemberBinding或CellTemplate定义列内容,而非使用ItemTemplate。当前写法同时定义两种布局规则,导致内容无法渲染。

两种修正方案:

方案一:保留GridView,用CellTemplate定义列内容

<ListView x:Name="listviewPlayers"  ItemsSource="{Binding Players}" Height="200">
    <ListView.View>
        <GridView>
            <GridViewColumn Width="235">
                <GridViewColumn.Header>
                    <Label Content ="Name" Foreground="Black" FontSize="10"></Label>
                </GridViewColumn.Header>
                <GridViewColumn.CellTemplate>
                    <DataTemplate DataType="local:Player">
                        <Label Content="{Binding Name}" FontWeight="Bold" FontSize="10" Foreground="Black"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Width="235">
                <GridViewColumn.Header>
                    <Label Content ="Score" Foreground="Black" FontSize="10"></Label>
                </GridViewColumn.Header>
                <GridViewColumn.CellTemplate>
                    <DataTemplate DataType="local:Player">
                        <Label Content="{Binding CurrentScore}" FontSize="10" HorizontalContentAlignment="Center" Foreground="Black"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Width="235">
                <GridViewColumn.Header>
                    <Label Content ="Games" Foreground="Black" FontSize="10"></Label>
                </GridViewColumn.Header>
                <GridViewColumn.CellTemplate>
                    <DataTemplate DataType="local:Player">
                        <Label Content="{Binding GamesWon}" HorizontalContentAlignment="Center" FontSize="10" Foreground="Black"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

方案二:移除GridView,仅使用ItemTemplate

若不需要GridView的列布局,直接去掉ListView.View部分,保留正确的ItemTemplate即可:

<ListView x:Name="listviewPlayers"  ItemsSource="{Binding Players}" Height="200">
    <ListView.ItemTemplate>
        <DataTemplate DataType="local:Player">
            <Grid Height="25">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="235"/>
                    <ColumnDefinition Width="235"/>
                    <ColumnDefinition Width="235"/>
                </Grid.ColumnDefinitions>
                <Label Content="{Binding Name}" FontWeight="Bold" FontSize="10" Foreground="Black"/>
                <Label Grid.Column="1" Content="{Binding CurrentScore}" FontSize="10" HorizontalContentAlignment="Center" Foreground="Black"/>
                <Label Grid.Column="2" Content="{Binding GamesWon}" HorizontalContentAlignment="Center" FontSize="10" Foreground="Black"/>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

3. 运行时DataContext检查

你仅设置了设计时的DataContext(d:DataContext),运行时需确保MainWindow的DataContext绑定到MainPageViewModel实例,可在MainWindow构造函数中添加:

public MainWindow()
{
    InitializeComponent();
    DataContext = new MainPageViewModel();
}

4. 额外优化建议

  • Players属性的setter中,每次赋值都会向PlayerNames添加所有Player的Name,多次赋值会导致重复数据,建议先清空再添加:
    set
    {
        players = value;
        PlayerNames.Clear();
        foreach (Player p in players)
        {
            PlayerNames.Add(p.Name);
        }
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Players)));
    }
    
  • 使用nameof()代替硬编码属性名,避免拼写错误:PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Players)));

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 02:29:59