0

I have a gridview shown as below in XAML

<ListView x:Name="listTasks">
        <ListView.View>
            <GridView x:Name="gridTasks">
                <GridViewColumn Header="ID" HeaderStringFormat="Lowercase" Width ="26" DisplayMemberBinding="{Binding id}"/>
                <GridViewColumn Header="Something" Width="113" DisplayMemberBinding="{Binding something}"/>
                <GridViewColumn Header="State" Width="179" DisplayMemberBinding="{Binding currentState}"/>
            </GridView>
        </ListView.View>
    </ListView>

and i have a button which adds to this gridview using the below

m.myList.Add(new mylistview.myitems
        {
            id = m.id,
            something= m.something,
            currentState = m.currentState,
        });

This button works perfectly by adding the row into the gridview. However I would like to modify theCurrentState using a method that is running. How would I locate for example, ID = "8" and then modify theCurrentState for that row?

UPDATED CODE SHOWN I've now replaced my list<Task> with ObservableCollection and managed to get it to add to my listview when I click onto my button. However, I am struggling to implement the iNotifyPropertyChanged into my code and getting it to work correctly... Below is my listview class

public class mylistview : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private string _currentState;
    public string currentState
    {
        get { return _currentState; }
        set
        {
            _currentState = value;
            OnPropertyChanged();
        }
    }

    public ObservableCollection<myitems> _myList = new ObservableCollection<myitems>();
    public ObservableCollection<myitems> myList
    {
        get { return _myList; }
    }

    private static int _id = 0; 

    public class myitems
    {
        public int id { get; set; }
        public string something{ get; set; }
        public string currentState { get; set; }
    }

    public int id
    {
        get { return _id; }
        set { _id = value; }
    }
}
m00shii
  • 7
  • 5

2 Answers2

0

Maybe with

listOfTasks.Items.Cast<ListViewItem>().First(item => item.ID == "8").theCurrentState = newState;
//I'm not sure about the Cast stuff, because I don't know what types the ListView uses for its items

Of course you could iterate through the items with a loop and check manually for the ID as well.

MetaColon
  • 2,895
  • 3
  • 16
  • 38
0

So I see you're using data bindings already, that's good. But your question makes me think you haven't quite grasped everything it can do for you yet.

My recommendation would be to forget about adding items directly to listOfTasks.Items. Instead you should make an ObservableCollection to hold that list and bind the listOfTasks to it. Like so:

ObservableCollection tasks = new ObservableCollection<mylistview.myitems>();
ListOfTasks.ItemsSource = tasks;

With that binding in place you should be able to simply add new items to the tasks list when they click your button:

tasks.Add(new mylistview.myitems
    {
        id = theId,
        something= something,
        currentState = theCurrentState,
    });

and it should automatically update the GUI. The last step is to make sure that the class mylistview.myitems implements INotifyPropertyChanged. This is easier than it sounds; you just need to have it trigger an event any time the property is set. Something like so:

public class exampleProperties: INotifyPropertyChanged
{
    //this is the event you have to emit
    public event PropertyChangedEventHandler PropertyChanged;

    //This is a convenience function to trigger the event.
    //The CallerMemberName part will automatically figure out 
    //the name of the property you called from if propertyName == ""
    protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName);
        }
    }

    //Any time this property is set it will trigger the event
    private string _currentState = "";
    public string currentState
    {
        get { return _currentState; }
        set
        {
            if (_currentState != value)
            {
                _currentState = value;
                OnPropertyChanged();
            }
        }
    }
}

Now that the gridview is bound to an ObservableCollection and the items held in that collection can notify interested GUI controls that their properties have changed, you should simply be able to update the GUI simply by changing the appropriate item in the collection.

And here's an example of a form that uses the whole technique: https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).asp

edit

I forgot that you specifically need to bind to the ItemSource property of the ListView. The way I have done it in the past is to set ItemsSource={binding} in the ListView's xaml and then assign an ObservableCollection to ListView.DataContext. However I have found an easier way and updated the original post with it. Here's a reference: http://www.wpf-tutorial.com/listview-control/listview-with-gridview/

Edit 2

Aha, you're adding the iPropertyChangedNotify to the wrong thing. It goes on the myitems class like so:

public class myitems : iNotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private int _id;
    public int id 
    { 
        get { return _id; }
        set
        {
            _id = value;
            OnPropertyChanged();
        }
    }

    public string something{ get; set; }
    public string currentState { get; set; }
}

I leave updating the current state and something properties as an excersize. They also need to trigger the OnPropertyChanged event when their value is set.

ashbygeek
  • 759
  • 3
  • 20
  • Thanks for your assistance and direction. I've added the `ObservableCollection tasks = new ObservableCollection`. But `datacontext` does not exist for `gridOfTasks`, however it does for `listOfTasks`. I've tried `listOfTasks` but the button no longer works with this. Any ideas please? – m00shii Mar 15 '17 at 08:17
  • And that's what I get for not actually testing the code before testing it. You are absolutely right about that and I forgot another important step. On the list view's xaml you need to add `itemssource={binding}`. I will also update my answer. – ashbygeek Mar 15 '17 at 10:51
  • Once again thank you for spending the time to assist me. Much appreciated. – m00shii Mar 15 '17 at 10:54
  • No problem! Hope I did t forget anything this time because I'm not at a computer where I could test my new code changes. :/ – ashbygeek Mar 15 '17 at 11:02
  • I've found this question below which looks very similar to your suggestion. I've tried it with my code, but not with the `iNotifyPropertyChanged` section just yet. Testing without it, the data isn't added to my list and I'm guessing this is normal behavior as the UI is not aware of any changes? http://stackoverflow.com/questions/10659347/bind-an-observablecollection-to-a-listview – m00shii Mar 15 '17 at 11:13
  • The `inotifypropertychanged` shouldn't change whether things get added to the list, it should only effect whether or not the list view updates when you change a specific object's properties. The data binding and the observable collection take care of making the listview show new and removed items. That link uses some fancy data binding that I'm unfamiliar with. Data bindings are all dependant on context and it looks like he set up an overall context for his entire xaml and then binds the items source of his list view to a property. – ashbygeek Mar 15 '17 at 11:41
  • I've got the `ObservableCollections` working now thanks to you and you've taught me something new. Appreciate it :) I will test the `iNotify` when I get home this evening and hopefully all is well. Thanks once again! – m00shii Mar 15 '17 at 13:01
  • No problem! Glad to help. WPF bindings confused the stew out of me for a bit when I first got into them so I'm glad to have helped straighten out your confusion. – ashbygeek Mar 15 '17 at 15:53
  • I'm still struggling to implement the `iNotifyPropertyChanged` despite you saying that it is easy haha I have tried various implementations found but nothing seems to fire the `iNotifyPropertyChanged`. Would simply doing `currentState = "something new"` fire the `iNotifyPropertyChanged`? – m00shii Mar 15 '17 at 18:01
  • If you edit your post above with your most recent attempt to implement the `iNotifyPropertyChanged` interface, particularly including the mylistview.myitems class, then I can do a better job of explaining that part of the system. – ashbygeek Mar 15 '17 at 18:13
  • Updated as requested. Please excuse the coding as I am still new as you could see lol – m00shii Mar 15 '17 at 18:35
  • Genius! What can I say! I've tried everything I could think of and was thinking why do I actually have the `currentState` twice. Working absolutely as I want it too! Thank you ever so much! – m00shii Mar 16 '17 at 17:21