如何在Silverlight 4中绑定到单例属性?

9

大家好,这是我在这里的第一篇帖子 :) 让我们从我正在使用的代码片段开始:

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() { ... }
}

正如您所看到的,它是一个单例类。 在我的看法中,我希望将控件绑定到MyProperty。我的最初想法是在视图中使用类似以下内容导入MyClass作为静态资源:

<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>

然后像这样绑定它:

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

当然,这种方法行不通,因为MyClass构造函数是私有的。我也不能使用x:static,因为它在Silverlight 4中不可用。 我被困在这个问题上比应该更长时间...我怎样才能绑定到MyProperty? 有什么想法吗? 提前感谢!
4个回答

8
我建议添加额外的类MyClassProvider:
public class MyClassProvider
{
    public MyClass MyClass { get { return MyClass.Instance; } }
}

这个类的实例可以放置在任何位置,并绑定到其MyClass属性。


5

你可以让你的用户控件内部通过自己的属性公开MyClass实例,并在本地绑定到自己的"MyClass"实例。由于它是一个单例,这将始终是相同的实例。


嗨,M. Copsey,我想尝试您的建议,但我必须承认我不太明白如何着手解决这个问题。我还是Silverlight/XAML编程的新手。如果您能详细说明一下,我将不胜感激 :) - Mathieu
@Tigel:这与下面Elad提出的选项基本相同。我只是建议让您的单例保持不变,但在控制器本身(非静态)中具有返回单一实例的属性。 - Reed Copsey
问题解决了。感谢各位的帮助!@Vladimir Dorokhov @Reed Copsey @Elad Katz - Mathieu

4
你可以稍微不同的实现单例模式,像这样:

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

现在你可以在XAML中执行以下操作:

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

然后像这样绑定:

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

请注意,单例模式仍然是单例模式,我们只是通过不将getter设置为静态来避开Silverlight缺少的静态特性。

我得等到明天才能试一下,但这看起来是一个不错的解决方法。然而,不在静态成员上有一个静态getter被认为是良好的实践吗?没有getter静态的后果是什么? - Mathieu
这是在Silverlight中实现MVVM时经常使用的内容,在由Laurent Bugnion(mvvmlight)提出的ViewModelLocator模式中,被广泛接受。 - Elad Katz
我记得在我的代码中的某些地方,我需要通过"MyClass.Instance.SomeMethod"调用来访问我的单例。如果getter不是静态的,这将是不可能的。 - Mathieu
你可以公开一个静态成员,不过想想看,@vladimir的解决方案比我的更好。 - Elad Katz

3

我已经验证了以下内容在Silverlight 5中可行:

保持你的类 MyClass 不变,然后在你的业务UserControl类中创建一个名为 MyClass MyClass 属性:

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

然后在您的业务 UserControl XAML 中,像这样进行绑定:
<TextBlock Text="Visibility Test" Visiblity="{Binding Path=MyClass.MyProperty, Converter={somexmlns:SomeVisiblityConverterIfNecessary}", ElementName="yourBusinessUserControlName"/>

如果在您的应用程序中的某个位置更改了MyClass.Instance.MyProperty(这里MyClass是类名),则上述绑定将被更新。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接