Developer
Developer

Reputation: 4321

How to bind to singleton object instance

So i have next class, called NavigationController it will control all actions related to navigation - menus, pages, popups etc.:

public class NavigationController: INotifyPropertyChanged
{
    #region ~~~ Fields ~~~

    private NavigationController instance;

    private bool isNavigationMenuOpen;

    #endregion
    #region ~~~ Constructors ~~~

    private NavigationController()
    {

    }

    #endregion
    #region ~~~ Events ~~~

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
    #region ~~~ Properties ~~~

    public NavigationController Instance
    {
        get
        {
            if(instance==null)
            {
                instance = new NavigationController();
            }

            return instance;
        }
    }

    public bool IsNavigationMenuOpen
    {
        get
        {
            return isNavigationMenuOpen;
        }

        set
        {
            if (isNavigationMenuOpen != value)
            {
                isNavigationMenuOpen = value;
                PropertyChanged(this, new PropertyChangedEventArgs("IsNavigationMenuOpen"));
            }
        }
    }

    #endregion
    #region ~~~ Methods ~~~

    public void OpenNavigationMenu()
    {
        this.IsNavigationMenuOpen = true;
    }

    public void CloseNavigationMenu()
    {
        this.IsNavigationMenuOpen = false;
    }

    #endregion
}

On my MainPage.xaml i have a Menu, that has a property IsPaneOpen and it is binded this way:

IsPaneOpen="{Binding IsNavigationMenuOpen, Source={StaticResource NavigationController}}"

So i'm adding NavigationController as a resource:

<Page.Resources>
    <controllers:NavigationController x:Key="NavigationController"/>
</Page.Resources>

And get error:

XAML NavigationController type cannot be constructed. In order to be constructed in XAML, a type cannot be abstract, interface, nested, generic or a struct, and must have a public default constructor

But the code3 above is not binding to an instance, it will create new object. How can i bind to an instance?

So as suggested here, i changed to this:

private static NavigationController instance;


public static NavigationController Instance
    {
        get
        {
            if(instance==null)
            {
                instance = new NavigationController();
            }

            return instance;
        }
    }

And the path:

<ToggleButton VerticalAlignment="Stretch" HorizontalAlignment="Stretch" IsChecked="{Binding Path=NavigationController.Instance.IsNavigationMenuOpen, Mode=TwoWay, Source={StaticResource NavigationController}}">
        <Image Source="ms-appx:///Assets/Icons/menu-icon.png"></Image>
    </ToggleButton>

And made constructor public

And still when i toggle the button in one control, the other control doesn't react. What is the problem? I think two instances were created for each control...

Upvotes: 1

Views: 1118

Answers (2)

birken25
birken25

Reputation: 373

You need to reference that Instance property in your XAML. So, when binding, you'll need to dot into it (and remove the static from Instance).

Instance.IsNavigationMenuOpen

However, as indicated in the other answer, consider a new design. Perhaps build a new type exposing a singleton instance that all other controller types can reference. That way, at least, it untangles it a bit.

Upvotes: 0

Mart&#237;n Misol
Mart&#237;n Misol

Reputation: 333

To correctly implement the Singleton pattern the Instance property should be static

Upvotes: 0

Related Questions