0

What is the easiest way to fire a callback/handler function when a list of strings changes but also when it's re-bound.

I tried switching from List to ObservableCollection and using CollectionChanged it does work on Add/Remove, but I also need it to work like this when I re-bind the list using "= new".

static class GlobalProperties
{
    private static ObservableCollection<string> _mylist = new ObservableCollection<string>();

    public static ObservableCollection<string> MyList
    {
        get
        {
            return _mylist ;
        }
        set
        {
            _mylist = value;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        Globals.MyList.CollectionChanged += HandleChange;
    }

    public static void HandleChange(object sender, NotifyCollectionChangedEventArgs e)
    {
        Console.WriteLine("test");
    }
}

I need to be able to attach a handler/callback function to - also when setting the property, and not just when adding or removing. This needs to be possible from the main function of the console application.

Dac0d3r
  • 2,176
  • 6
  • 40
  • 76
  • where are you stuck? you seem to be on the right track. you an just add your function to your `set { }` and as a listener to the `_mylist` – Neville Nazerane Jan 17 '18 at 23:38
  • I have these 2 files. The Program.cs with the main function and this GlobalProperties.cs which has a bunch of static properties. The handler function needs to be outside the GlobalProperties (right now in Program.cs, main function), so wouldnt it create a circular dependency to refer a function in Program.cs from GlobalProperties.cs when Program.cs already uses GlobalProperties.cs? – Dac0d3r Jan 17 '18 at 23:41
  • Why not add a `CollectionChanged` event to the `GlobalProperties` class, and call it in the setter `if (_mylist != value)`? – Rufus L Jan 17 '18 at 23:47
  • Well I might end up doing just that, but ideally I'd prefer to keep only the observable global properties there. Also the handler function might need to be in another context/scope with variables and logic which is not accessible from within the GlobalProperties class. – Dac0d3r Jan 17 '18 at 23:52

1 Answers1

2

You could use this:

static class GlobalProperties
{
    private static ObservableCollection<string> _mylist = new ObservableCollection<string>();

    public static ObservableCollection<string> MyList
    {
        get
        {
            return _mylist;
        }
        set
        {
            if (_mylist == value) return; // suggested on comment. Relocate if you still need to run GotUpdated()
            _mylist = value;
            GotUpdated();
            _mylist.CollectionChanged += (sender, e) => GotUpdated();
        }
    }


    public static Action GotUpdated { private get; set; }

}
Neville Nazerane
  • 6,622
  • 3
  • 46
  • 79
  • check this if you want to make it as an event https://stackoverflow.com/questions/623451/how-can-i-make-my-own-event-in-c – Neville Nazerane Jan 17 '18 at 23:49
  • 1
    Won't this add a duplicate event delegate on every set? – Jonathon Chase Jan 17 '18 at 23:54
  • no, it is done after the new _mylist object is assigned. Unless the same object is being reassigned, in which case we can `=+` first – Neville Nazerane Jan 17 '18 at 23:55
  • Thanks. A question to your code. How would I define the handler function outside GlobalProperties - eg. in Program.cs -> main function? I cannot do this: "Globals.GotUpdated = HandleChange;" Getting the error: No Overload for 'HandleChange' matches delegate 'Action' – Dac0d3r Jan 18 '18 at 00:00
  • 1
    Or in the setter you can just add the first line: `if (_mylist == value) return;` – Rufus L Jan 18 '18 at 00:04
  • Well if you want to use it as an event, you can check the link in my first comment on how to make an event instead of `Action GotUpdated`. Else if you don't need the parameters in your `HandleChange` function, you can use `Globals.GotUpdated = () => HandleChange()` – Neville Nazerane Jan 18 '18 at 00:05
  • @RufusL yes, that if statement can be added in any line according to the OPs requirement. For instance if he still needs to run the `GotUpdated()` – Neville Nazerane Jan 18 '18 at 00:07
  • It would be sweet to be able to do: Globals.GotUpdated = `(myParam) => HandleChange(myParam);`, but then I'd need to go the events route? – Dac0d3r Jan 18 '18 at 00:10
  • 1
    no you can do `Action GotUpdated` instead of `Action GotUpdated`. – Neville Nazerane Jan 18 '18 at 00:42