wpflistviewdata-bindingdatatemplate

WPF Databinding in Listview


I have the following ListView that I wish to bind to a custom list in my viewmodel:

<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>

In my viewmodel I have Players:

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"));
        }


    }

And a Player looks like this:

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")); }
    }

What am I doing wrong with my ListView DataTemplate bindings? I have set this on the MainWindow:

d:DataContext="{d:DesignInstance Type=local:MainPageViewModel}"

At the moment the ListView looks like this:

enter image description here

Any advice would be appreciated.

Thanks,

Mike


Solution

  • You must not set the ItemTemplate property of the ListView.

    Set the GridViewColumns' DisplayMemberBinding property instead.

    <ListView x:Name="listviewPlayers" ItemsSource="{Binding Players}" Height="200">
        <ListView.View>
            <GridView>
                <GridViewColumn Width="235" Header="Name"
                                DisplayMemberBinding="{Binding Name}"/>
                <GridViewColumn Width="235" Header="Games"
                                DisplayMemberBinding="{Binding CurrentScore}"/>
                <GridViewColumn Width="235" Header="Score"
                                DisplayMemberBinding="{Binding GamesWon}"/>
            </GridView>
        </ListView.View>
    </ListView>
    

    If you want to explicitly set the UI elements of the header and the cell content, write the GridViewColumn declarations like this:

    <GridViewColumn Width="235">
        <GridViewColumn.Header>
            <TextBlock Text="Name"/>
        </GridViewColumn.Header>
        <GridViewColumn.CellTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}"/>
            </DataTemplate>
        </GridViewColumn.CellTemplate>
    </GridViewColumn>