3

I am very new to the concept of data binding and I don't think I understood it completely. I have a class named Project with a LinkedList of type ToDo as one of its properties. When I navigate to one instance of Project, I will display the LinkedList of type ToDo in a ListView. I have created functions that allow me to change the sequences of the nodes in the LinkedList (move up, move down) and to remove the selected node (delete). I want the ListView to refresh whenever there is a change in the LinkedList, (move up, move down or delete). However, I cannot achieve that. Here is my code: (not all parts are included)

XAML of the page:

<ListView x:Name="myListView" ItemsSource="{Binding Source={StaticResource ToDos}, Mode=TwoWay}">    
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <CheckBox x:Name="myCheckBox" 
                          Content="{Binding ToDoTitle, Mode=TwoWay}" 
                          IsChecked="{Binding IsCompleted, Mode=TwoWay}">                         
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>      
</ListView>

C# for DataModel:

public class ToDo : INotifyPropertyChanged
{
    private string toDoTitle;
    private bool isCompleted;
    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    public string ToDoTitle { get { return this.toDoTitle; } set { this.toDoTitle = value; this.OnPropertyChanged(); } }
    public bool IsCompleted { get { return this.isCompleted; } set { this.isCompleted = value; this.OnPropertyChanged(); } }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // Raise the PropertyChanged event, passing the name of the property whose value has changed.
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

}

public class Projects : INotifyPropertyChanged
{
    private LinkedList<ToDo> toDos;

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public LinkedList<ToDo> ToDos { get { return this.toDos; } set { this.toDos = value; this.OnCollectionChanged(); } }

    public Projects()
    {
        ToDos = new LinkedList<ToDo>();

    }
    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // Raise the PropertyChanged event, passing the name of the property whose value has changed.
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

Thank you.

Alexander
  • 4,153
  • 1
  • 24
  • 37
pomeloyou
  • 157
  • 2
  • 10

1 Answers1

0

First I would advise you to read about MVVM, and try to follow some basic tutorials like this one.

You can use MVVM Light to avoid managing the INotifyPropertyChanged by yourself at first (but it's really good to know how MVVM light work under the hood).

To come back to your problem, your current code notifies only if you set the full ToDos list. If you want to be aware of any change in a list (seing when an item is add/remove/update), you are probably looking for an ObservableCollection, not a LinkedList.

Hope it helps.

Community
  • 1
  • 1
Ouarzy
  • 3,015
  • 1
  • 16
  • 19
  • I agree - the quickest solution would be to replace the `LinkedList` with an `ObservableCollection`. It implements a similar interface as the `INotifyPropertyChanged`: [INotifyCollectionChanged](https://msdn.microsoft.com/en-us/library/system.collections.specialized.inotifycollectionchanged%28v=vs.110%29.aspx) – Manfred Radlwimmer May 09 '16 at 09:24
  • @ManfredRadlwimmer Thanks for the answer, but I wish I can keep the linkedlist because I made use of several linkedlist's methods and I would like to keep them. Is there any way I can keep the linkedlist while implementing INotifyPropertyChanged/NotifyCollectionChanged to make this work? – pomeloyou May 09 '16 at 12:15
  • Not really, no. Is there a particular reason why you used a `LinkedList`? Some Feature that don't exist in `ObservableCollection`? In most cases methods that use any kind of List work just as well with one of the common interfaces (`IEnumerable`, `ICollection`, `IList`, etc.). – Manfred Radlwimmer May 09 '16 at 12:27
  • @ManfredRadlwimmer So, I tried this: continued using linkedlist, added an observablecollection which imports values from the linkedlist and bind this observablecollection to my listview. However, using breakpoint to analyse when the app is running, I realized that modifying the linkedlist (add/remove/update) does not trigger OnPropertyChanged as the get and set accessors are not triggered. So, I tried directly calling OnPropertyChanged when a modification is done (add/remove/update). The OnProperyChanged functions executed but the UI did not change. – pomeloyou May 09 '16 at 14:01
  • @ManfredRadlwimmer when the OnPropertyChanged function is executed, the ListView should be refreshed right? – pomeloyou May 09 '16 at 14:02
  • @ManfredRadlwimmer Solved my own problem! I could keep my linkedlist without using observablecollection or INotifyPropertyChanged or MVVM Light. Sticking with my linkedlist, after every modification to the linkedlist where I need a refresh of ListView, I just set the CollectionViewSource.Source to the linkedlist again. It is probably not the most elegant solution but I am rushing for a deadline. I will read up more on MVVM Light and ObservableCollection to deepen my data binding's understanding. Thanks for the help. :D – pomeloyou May 09 '16 at 18:11
  • @pomeloyou You are welcome, please make sure to accept an answer (checkmark on the left) to mark this question as resolved. – Manfred Radlwimmer May 09 '16 at 18:13
  • Thanks Manfred Radlwimmer and glad you found a solution pomeloyou. As you notice it is not the most elegant solution, but at least you get the idea: if you update the full datasource it will notify the UI. – Ouarzy May 10 '16 at 08:16