-1

My goal is to have a singletin with my application shared data, preferences, etc. Want it to be singleton across my entire application and want it to be 2 way bindable in WPF using INotify.

I read that .net 4.5 can utilize StaticPropertyChanged so I wonder if the below is how I would implement it as documentation seems spotty for this.

public static class Global
{
    public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;
    private static void CallPropChanged(string Prop)
    {
        StaticPropertyChanged?.Invoke(Settings, new PropertyChangedEventArgs(Prop));
    }
    private static Store Settings = new Store();

    public static int setting1
    {
        get { return Settings._setting1; }
        set { if (value != Settings._setting1) { Settings._setting1 = value; CallPropChanged("setting1"); } }
    }
}

internal sealed class Store
{
    internal int _setting1;
}

Am I on the right track for what I want to accomplish?

Edit: Made some modifications:

public sealed class Global:INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    static readonly Global _instance = new Global();

    private int _setting1;
    private int _setting2;

    private void CallPropChanged(string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        CallPropChanged(propertyName);
        return true;
    }

    private Global() { }

    public static int setting1
    {
        get { return _instance._setting1; }
        set { _instance.SetField(ref _instance._setting1, value); }
    }
    public static int setting2
    {
        get { return _instance._setting2; }
        set { _instance.SetField(ref _instance._setting2, value); }
    }

}
Wobbles
  • 3,033
  • 1
  • 25
  • 51
  • Did what you tried work? If so, what's your question? If not, what happened and what _specifically_ do you need help with? It seems to me that if you're implementing a singleton (the code you posted does no such thing), then the singleton object itself can just implement `INotifyPropertyChanged` as usual. Please improve the question so that it's clear what you're actually having trouble with. Make sure you include a good [mcve] that reliably reproduces whatever problem you're running into. – Peter Duniho Oct 04 '16 at 20:23
  • @PeterDuniho Is not defining an instance store inside a static one way to create a singleton? Or does it still create a new instance of the store from each call? I want to bind to the static, and static cannot implement INotify – Wobbles Oct 04 '16 at 20:29
  • _"Is not defining an instance store inside a static one way to create a singleton?"_ -- no. The term "singleton" has a very specific meaning, and does not apply to the code you posted. With a singleton, you'll have a `public static` property that returns the _single_ instance of your class, but the class itself and all its members are still non-static. Then you can implement interfaces (like `INPC`). You may _instead_ use `StaticPropertyChanged`, but that's not a singleton. It's just a static class that WPF can deal with. See e.g. [this answer](http://stackoverflow.com/a/9786554) for more. – Peter Duniho Oct 04 '16 at 20:37
  • @PeterDuniho Does the Singleton approach hold any benefit? Can I bind to a singleton at design time? – Wobbles Oct 04 '16 at 20:40
  • _"Does the Singleton approach hold any benefit?"_ -- with a singleton, you can implement any interface you want/need. This isn't possible with static classes in C#. _"Can I bind to a singleton at design time?"_ -- I don't know why you wouldn't be able to. Did you try? Did you have any specific problems doing so? If you can bind to a static property (which you can), naturally you can bind to an instance of a class returned by a static property. – Peter Duniho Oct 04 '16 at 20:44
  • @PeterDuniho well Its sort of just academic right now, want to make sure I have the right approach before I build too much on top of it. I added another sample of code, does this look more like a singleton? do you see any problems with this approach? – Wobbles Oct 04 '16 at 23:01
  • The code still isn't a singleton. Also the updated code won't work for binding, because while the `PropertyChanged` event is public, there's no public instance of the object for anything to bind to. I don't see what your fixation on the singleton question is; if public static properties suffice for your needs, why does the singleton pattern come into the discussion at all? Bottom line: I still don't really understand what you're asking here. "Academic" isn't on-topic, as it tends to be "primarily opinion based". A good question for Stack Overflow has a specific problem one is trying to solve. – Peter Duniho Oct 05 '16 at 00:10
  • @PeterDuniho How is it not a singleton, it implements the singleton pattern from MSDN and the binding seems to work fine – Wobbles Oct 05 '16 at 10:44
  • The binding has **nothing** to do with whether it's a singleton. And I'm positive that whatever MSDN page you're talking about, it is not true that _"it implements the singleton pattern from MSDN"_. Either the page you're referring to does not actually show a singleton pattern implementation, or you did not in fact follow the example on the page. I suppose there's a remote possibility MSDN has an incorrect description of the singleton pattern, but that seems highly unlikely to me. See https://en.wikipedia.org/wiki/Singleton_pattern. – Peter Duniho Oct 05 '16 at 15:32
  • And as far as the binding goes, the code you posted doesn't have a `PropertyChanged` event that WPF can subscribe to, so while you might find binding work when the properties are set before the binding is created, it won't be dynamic. I.e. changes to properties won't be reflected in the target of the binding. – Peter Duniho Oct 05 '16 at 15:35
  • @PeterDuniho What? Yes it absolutely does, it implement INotify and has a `PropertyChanged` event, are you looking at the code I added above or something else? – Wobbles Oct 06 '16 at 12:44
  • _"it implement INotify and has a PropertyChanged event"_ -- yes, it does. But WPF has no way to obtain the object implementing the interface, and so cannot subscribe to the event. – Peter Duniho Oct 06 '16 at 15:32
  • @PeterDuniho Then why does it work? – Wobbles Oct 06 '16 at 16:27
  • I doubt it does. The bound value will be fine initially, but if you ever change the property value, the code you've shown has no way to notify WPF of the property change. If the displayed value does update, then you've got something somewhere else that is causing that to happen. That doesn't change the fact that the code you posted doesn't implement the singleton pattern, and that it doesn't provide a means for property-change notifications to WPF. If you want more specific information, you need to provide a good [mcve]. I can comment only on the little bit of code you've shared so far. – Peter Duniho Oct 06 '16 at 16:57
  • @PeterDuniho You keep saying it doesn't work, yet it does, already tried it, and it does implement both the singleton patter and INotify, I think you must be looking at the wrong code.... – Wobbles Oct 06 '16 at 17:02
  • First, there is **no question at all** that the code you posted does not implement the singleton pattern. That is a simple matter of fact that can be readily seen. If you think otherwise, you simply don't understand what the singleton pattern is. As for the property-change notification. **Prove it.** Post a good [mcve] that uses _exactly_ the code you posted above, and nothing more, as the data source for a XAML data binding scenario, where you can change the property value, and the target property will be updated to match. That your class has implemented the interface doesn't mean it _works_. – Peter Duniho Oct 06 '16 at 17:14

1 Answers1

0

I'm not familiar with StaticPropertyChanged, but I have implemented singleton viewmodels like this:

public class MyViewModel : ViewModelBase 
{
    public static MyViewModel Instance { get; set; }
    public static ICommand MyCommand { get; set; }

    public MyViewModel()
    {
        Instance = this;
    }
}

and bound buttons, etc in XAML like this:

<Button Content="Click Me" Command="{x:Static vm:MyViewModel.MyCommand}" CommandParameter="MyParameters" />

You can use the x:Static prefix to bind to the static fields, and you can use INotifyPropertyChanged normally... You may notice that this particular binding doesn't actually require the singleton instance of the VM, but to stick with the singleton model, you can also bind to {x:Static vm:MyViewModel.Instance.Whatever}

Dave Smash
  • 2,941
  • 1
  • 18
  • 38
  • Im assuming you need to access the properties through `Instance`, and whats the point of a static property inside an instance? Does `MyCommand` need to be an instance? Only reason to make `MyCommand` static is if it was a shortcut to access a `MyViewModel.Instance._MyCommand` field? Right? Or am I just lost lol. – Wobbles Oct 04 '16 at 22:51
  • The above is not a singleton implementation either. The singleton pattern has some specific requirements, one of which is that it is _not possible_ to create more than one instance of the type. The constructor is private, and there is a static field storing the _single_ instance of that type, and which is initialized only once. A better implementation of the pattern also would not initialize the field in the constructor. In .NET, the `Lazy` class is useful for singletons that are costly to create and not always used, otherwise a simple field initializer suffices. – Peter Duniho Oct 05 '16 at 00:13
  • @PeterDuniho My 2nd example has that yet you say that that isn't a singleton either. I'm copying my code from singleton examples so I'm not sure what else there is. – Wobbles Oct 05 '16 at 10:39
  • _"My 2nd example has that"_ -- has what? Part of the singleton pattern is that the single instance can be used outside of the singleton class. Your second example certainly doesn't have that. The instance of `Global` is private to the class; there's nothing there that would allow any other code to access it. – Peter Duniho Oct 05 '16 at 15:36
  • @PeterDuniho What are you talking about, the static properties are public and expose the instance... I don't think you are looking at the right code. – Wobbles Oct 06 '16 at 12:45
  • @Wobbles: _"the static properties are public"_ -- yes, they are. _"and expose the instance"_ -- no, they don't. They return values _from_ the instance, but the instance itself remains encapsulated and private to the class. – Peter Duniho Oct 06 '16 at 15:31
  • @PeterDuniho so, I don't need to expose the instance because I don't care about it, only the fields within it. – Wobbles Oct 06 '16 at 16:27
  • @Wobbles: _"I don't need to expose the instance because I don't care about it"_ -- impossible for me to say. You simply haven't provided enough detail. At the very least, if you want property-change notifications, you need to implement that _somewhere_. Without exposing the instance, the instance obviously isn't going to provide that, since WPF won't be able to subscribe to the `PropertyChanged` event. If you like, you can implement the public members all as `static` and include `StaticPropertyChanged`. But you still need to raise that event when a property changes, _somehow_. – Peter Duniho Oct 06 '16 at 17:00