Search code examples
c#wpflistviewdata-bindingbinding

ListView keeps empty when i bind same property to another ListView


If i bind the same property to another control of same type, in my case to a ListView then the first ListView will be filled with object but the second ListView keep empty. i played arround with OneWay and TwoWay mode but until now i cant find a solution to show same entries in both ListViews. enter image description here

Here is my Code. I hope you can help me. p.s. I use MVVM

App.Xaml.cs

using System.Windows;

namespace WPF_TestApp
{
    public partial class App : Application
    {
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            MainWindow mainWindow = new MainWindow();
            mainWindow.Show();
        }
    }
}

MainView.xaml

<Window x:Class="WPF_TestApp.MainWindow"
        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:local="clr-namespace:WPF_TestApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Border Grid.Column="0" BorderBrush="#FF313131" BorderThickness="1" CornerRadius="0,0,5,5" Margin="5,0,5,5">
            <ListView
              AlternationCount="2"
              ItemsSource="{Binding Items}"/>
        </Border>
        <Border Grid.Column="1" BorderBrush="#FF313131" BorderThickness="1" CornerRadius="0,0,5,5" Margin="5,0,5,5">
            <ListView 
              AlternationCount="2"
              ItemsSource="{Binding Items}"/>
        </Border>
    </Grid>
</Window>

MainView.xaml.cs

using System.Windows;
using WPF_TestApp.MVVM.ViewModel;

namespace WPF_TestApp
{
    public partial class MainWindow : Window
    {
        public MainViewModel viewModel {  get; set; }

        public MainWindow()
        {
            viewModel = new MainViewModel();
            InitializeComponent();
            this.DataContext = viewModel;
        }
    }
}

MainViewModel.cs

using Caliburn.Micro;
using System.Windows.Controls;

using WPF_TestApp.MVVM.Model;

namespace WPF_TestApp.MVVM.ViewModel
{
    public class MainViewModel
    {
        public MainModel Model { get; set; }
        public BindableCollection<ListViewItem> Items { get; set; }


        public MainViewModel()
        {
            Model = new MainModel();
            Items = Model.Items;
        }

    }
}

MainModel.cs

using Caliburn.Micro;
using System.Windows.Controls;

namespace WPF_TestApp.MVVM.Model
{
    public class MainModel
    {
        public BindableCollection<ListViewItem> Items {  get; set; }
        public MainModel()
        {
            Items = new BindableCollection<ListViewItem>();

            for(int i = 0; i<=100; i++)
            {
                ListViewItem item = new ListViewItem();
                item.Content = $"Item >>>{i.ToString()}";
                Items.Add(item);
            }
        }
    }
}


Solution

  • The problem is that you add ListViewItems manually to the Items collection. A ListViewItem is a UI element that can only have a single parent element in the visual tree. It can not be contained in two visual trees, i.e. two ListViews at the same time.

    Instead of BindableCollection<ListViewItem>, use BindableCollection<string>. A ListViewItem will automatically be created for each string item in the ListView.

    public class MainModel
    {
        public BindableCollection<string> Items { get; } = new BindableCollection<string>();
    
        public MainModel()
        {
            for (int i = 0; i < 100; i++)
            {
                Items.Add($"Item >>>{i}");
            }
        }
    }
    

    As a note, you would not use a ListView when you are not setting its View property, e.g. to a GridView. Use the simpler ListBox base class instead.