I have a very simple application, where I want populate the ListView
when the user presses a button. I am using CollectionViewSource
to update the ListView
when the button is pressed, but I cannot populate the ListView
items.
Here is the xaml
containing 2 buttons and a ListView
:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Margin="20" Grid.Row="0" Orientation="Horizontal">
<Button Command="{Binding GetAllDoorItemsCommand}">Get All Door Items</Button>
<Button Margin="20,0,0,0">Modiy Door Open Close</Button>
</StackPanel>
<ListView Grid.Row="1" Margin="0,20,0,0" x:Name="lstViewLockItems" ItemsSource="{Binding DoorCollection}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Height="80" Width="80">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="pack://application:,,,/Images/door.jpg"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Open}" Value="True">
<Setter Property="Source" Value="pack://application:,,,/Images/dooropen.jpg"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
In the code behind, I am setting the DataContext
as follows:
public class MainWindowViewModel {
private ICollectionView _doorView;
public ICollectionView DoorCollection {
get {
return _doorView;
}
set {
_doorView = value;
}
}
public ICommand GetAllDoorItemsCommand {
get;
set;
}
public MainWindowViewModel() {
GetAllDoorItemsCommand = new RelayCommand < object > (GetAllItems);
}
private void GetAllItems(object obj) {
var Items = new List < Door > ();
Items.Add(new Door() {
Name = "Front", Open = true
});
Items.Add(new Door() {
Name = "Back", Open = false
});
DoorCollection = CollectionViewSource.GetDefaultView(Items);
DoorCollection.Refresh();
}
}
public class Door: INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private string _name;
public string Name {
get => _name;
set {
_name = value;
OnPropertyChanged("Name");
}
}
private bool _open;
public bool Open {
get => _open;
set {
_open = value;
OnPropertyChanged("Open");
}
}
protected virtual void OnPropertyChanged(string propertyName) {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
I would appreciate any help.
I have a very simple application, where I want populate the ListView
when the user presses a button. I am using CollectionViewSource
to update the ListView
when the button is pressed, but I cannot populate the ListView
items.
Here is the xaml
containing 2 buttons and a ListView
:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Margin="20" Grid.Row="0" Orientation="Horizontal">
<Button Command="{Binding GetAllDoorItemsCommand}">Get All Door Items</Button>
<Button Margin="20,0,0,0">Modiy Door Open Close</Button>
</StackPanel>
<ListView Grid.Row="1" Margin="0,20,0,0" x:Name="lstViewLockItems" ItemsSource="{Binding DoorCollection}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Height="80" Width="80">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="pack://application:,,,/Images/door.jpg"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Open}" Value="True">
<Setter Property="Source" Value="pack://application:,,,/Images/dooropen.jpg"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
In the code behind, I am setting the DataContext
as follows:
public class MainWindowViewModel {
private ICollectionView _doorView;
public ICollectionView DoorCollection {
get {
return _doorView;
}
set {
_doorView = value;
}
}
public ICommand GetAllDoorItemsCommand {
get;
set;
}
public MainWindowViewModel() {
GetAllDoorItemsCommand = new RelayCommand < object > (GetAllItems);
}
private void GetAllItems(object obj) {
var Items = new List < Door > ();
Items.Add(new Door() {
Name = "Front", Open = true
});
Items.Add(new Door() {
Name = "Back", Open = false
});
DoorCollection = CollectionViewSource.GetDefaultView(Items);
DoorCollection.Refresh();
}
}
public class Door: INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private string _name;
public string Name {
get => _name;
set {
_name = value;
OnPropertyChanged("Name");
}
}
private bool _open;
public bool Open {
get => _open;
set {
_open = value;
OnPropertyChanged("Open");
}
}
protected virtual void OnPropertyChanged(string propertyName) {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
I would appreciate any help.
Share Improve this question edited Apr 1 at 11:54 AztecCodes 5966 gold badges16 silver badges30 bronze badges asked Mar 28 at 18:32 nikhilnikhil 1,7603 gold badges26 silver badges64 bronze badges 3 |1 Answer
Reset to default 1According to the documentation (emphasis mine):
You can think of a collection view as a layer on top of a binding source collection that allows you to navigate and display the collection based on sort, filter, and group queries, all without having to manipulate the underlying source collection itself. If the source collection implements the INotifyCollectionChanged interface, the changes that raise the CollectionChanged event are propagated to the views.
So, the underlying collection is responsible for notifying about changes, and List
does not do that. A good choice would be ObservableCollection
. Here is a simplified implementation using your code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
GetAllDoorItemsCommand = new RelayCommand<object>(GetAllItems);
DoorCollection = CollectionViewSource.GetDefaultView(_doorView);
}
private readonly ObservableCollection<Door> _doorView = new();
public ICollectionView DoorCollection { get; }
public ICommand GetAllDoorItemsCommand { get; }
private void GetAllItems(object obj)
{
_doorView.Clear();
_doorView.Add(new Door { Name = "Front", Open = true });
_doorView.Add(new Door { Name = "Back", Open = false });
DoorCollection.Refresh();
}
}
DoorCollection
property is implemented. You are assigning a new value to it(CollectionViewSource.GetDefaultView(Items))
, but your UI isn't being notified that the DoorCollection property has changed. This is because you're not raising thePropertyChanged
event when settingDoorCollection
. – AztecCodes Commented Mar 28 at 19:01