How to bind to a singleton property in Silverlight

2019-06-16 05:04发布

问题:

Hi all first post here :) Let's start with a snippet of the code I'm using:

public MyClass : INotifyPropertyChanged
{
  private static MyClass _instance;
  public static MyClass Instance
  {
      get
      {
          if (_instance == null)
              _instance = new MyClass();
          return _instance;
      }
  }

  private bool _myProperty;
  public bool MyProperty
  {
      get
      {
        return _myProperty;
      }
      set
      {
          if (_myProperty!= value)
          {
              _myProperty= value;
              NotifyPropertyChanged("MyProperty");
          }
      }
   }

   private MyClass() { ... }
}

As you can see, it's a singleton class. In my view, I want to bind a control on MyProperty. My initial idea was to import MyClass as a static ressource in my view using something like:

<UserControl x:Class="Metrics.Silverlight.ChartView"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:logic="clr-namespace:Metrics.Logic;assembly=Metrics.Logic">
  <UserControl.Resources>
    <logic:MyClass x:Key="myClass" />
  </UserControl.Resources>
</UserControl>

And bind it like so:

<Button Margin="5" Click="btnName_Click"  Visibility="{Binding Source={StaticResource myClass}, Converter={StaticResource visibilityConverter}, Path=MyAttribute, Mode=OneWay}">

Of course, this approach won't work since MyClass constructor's is private. I also cannot use x:static since it's not available in Silverlight 4.

I've been stuck on this problem far longer than I should have... How can I bind on MyProperty?

Any ideas?

Thanks in advance!

回答1:

You could have your UserControl, internally, expose the MyClass instance through it's own property, and bind locally to it's own "MyClass" instance. Since it's a Singleton, this will always be the same instance.



回答2:

I advice to add additional class MyClassProvider:

public class MyClassProvider
{
    public MyClass MyClass { get { return MyClass.Instance; } }
}

Instance of this class you can place anywhere and bind to its MyClass property.



回答3:

You could implement the singleton slightly differently, like so:

  private static MyClass _instance;
  public MyClass Instance // note the getter is not static
  {
      get
      {
          if (_instance == null)
              _instance = new MyClass();
          return _instance;
      }
  }

so now you could do the following in xaml:

<UserControl x:Class="Metrics.Silverlight.ChartView"
  <UserControl.Resources>
    <logic:MyClass x:Key="myClass" />
  </UserControl.Resources>
</UserControl>

and bind it like this:

<Button Margin="5" Click="btnName_Click"  Visibility="{Binding Source={StaticResource myClass}, Converter={StaticResource visibilityConverter}, Path=Instance.MyAttribute, Mode=OneWay}">

notice that the singleton still is a singleton, but we just bypass Silverlight's missing static by not setting the getter as static.



回答4:

I have verified the following is working in Silverlight 5:

Keep your class MyClass unchanged, then create an property of MyClass with the name of MyClass in your business UserControl class:

public MyClass MyClass
{
    get { return <Namespace>.MyClass.Instance; }
}

Then in your business UserControl XAML, do binding like this:

<TextBlock Text="Visibility Test" Visiblity="{Binding Path=MyClass.MyProperty, Converter={somexmlns:SomeVisiblityConverterIfNecessary}", ElementName="yourBusinessUserControlName"/>

Once some where in your application, MyClass.Instance.MyProperty (here MyClass is the class name) changes the value of MyProperty, the above binding will be updated.