How to mimick the behaviour of an ObservableCollection for a List when it is a Source for a CollectionViewSource?

StackOverflow https://stackoverflow.com/questions/1667391

Question

The code below works as follows: a form is shown with a list of sorted names. When the button is clicked a new name is added to the list at the appropriate sorted position from the textbox . When an item of the list is doubleclicked it is prefixed with "AAA", which triggers it to be placed on top of the list. When I change the ObservableCollection to a List this behaviour disappears of course. But how can I mimick it??? I tried implementing INotifyPropertyChanged, I called the UpdateTarget() method on the listbox's BindingExpression, all to no avail...

I have the following XAML:

<Window x:Class="CollectionViewSpike.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<StackPanel>
    <TextBox Name="NewNameBox" Text="{Binding NewName, UpdateSourceTrigger=PropertyChanged}"/>
    <Button Click="Button_Click"">Add</Button>
    <ListBox Name="listbox" ItemsSource="{Binding MyCollectionViewSource.View}"
             MouseDoubleClick="listbox_MouseDoubleClick"/>
</StackPanel>

The code behind:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;

namespace CollectionViewSpike
{
   public partial class Window1: Window
   {
    public ObservableCollection<string> Names { get; set; }

    public static DependencyProperty NewNameProperty = DependencyProperty.Register("NewName", typeof (string),
                                                                           typeof (Window1),
                                                                           new PropertyMetadata(string.Empty));

    public string NewName
    {
        get { return (string) GetValue(NewNameProperty); }

        set{ SetValue(NewNameProperty,value);}
    }

    public Window1()
    {
        InitializeComponent();
        var names = new string[] { "onno", "friso","andre"};
        Names = new ObservableCollection<string>(names);
        collectionViewSource = new CollectionViewSource { Source = Names };
        collectionViewSource.SortDescriptions.Add(
                     new SortDescription("", ListSortDirection.Ascending));
        DataContext = this;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        NewName = NewName ?? "???";
        Names.Add(NewName);
        NewName = string.Empty;
    }

    private CollectionViewSource collectionViewSource;
    public CollectionViewSource MyCollectionViewSource
    {
        get { return collectionViewSource; }
        private set { collectionViewSource = value;}
    }

    private void listbox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        var user = (string)listbox.SelectedItem;
        int index = Names.IndexOf(user);
        Names[index]="AAA"+Names[index];
    }
}

}

Was it helpful?

Solution 2

Found it. Add MyCollectionViewSource.View.Refresh() to a method that changes the underlying non observable enumerable<T> Supposing that the Observable<string> Names is now a List<string> Names:

   private void Button_Click(object sender, RoutedEventArgs e)
    {
        NewName = NewName ?? "???";
        Names.Add(NewName);
        NewName = string.Empty;
        MyCollectionViewSource.View.Refresh();
    }

   private void listbox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        var user = (string)listbox.SelectedItem;
        int index = Names.IndexOf(user);
        Names[index]="AAA"+Names[index];
        MyCollectionViewSource.View.Refresh();
    } 

OTHER TIPS

I'm not sure why you wouldn't just use an ObservableCollection - that's what its for. But, anyway, you probably also have to implement INotifyCollectionChanged to let the binding know that the contents or ordering changed.

msdn reference for ObservableCollection

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top