【问题标题】:Binding visibility to static property将可见性绑定到静态属性
【发布时间】:2011-04-15 16:31:30
【问题描述】:

我有一个带有标签的控件,我想根据我的控件所有实例的全局菜单项来隐藏或显示该标签。如果我单击按钮隐藏标签,我想隐藏 all 它们。

我的 xaml 看起来像这样:

<TextBlock Name="_label" Visibility="{Binding LabelShown}" VerticalAlignment="Center" HorizontalAlignment="Center"/>

在我的代码后面我有一个属性:

    private static Visibility _labelShown;
    public static Visibility LabelShown
    {
        get { return _labelShown; }
        set { _labelShown = value; }
    }

我设置DataContext = this;

当我更改静态属性时,什么也没有发生。我认为这是因为没有控件收到属性更改通知。我无法在其上实现 INotifyPropertyChanged,因为我无法从我的静态属性中引用非静态属性更改处理程序。

我觉得这可能不是最好的方法,但我真的希望有一个按钮(在我的实际控制之上的许多级别)驱动所有实例的可见性。

【问题讨论】:

    标签: c# wpf binding


    【解决方案1】:

    CodeNaked 的解决方案有效,但它使用单例,在进行单元测试时有缺点。我更喜欢通过在应用程序根目录下设置一个设置实例来解决全局访问问题,即App-class。

    例如

    public partial class App : Application
    {
        private static Settings _settings = new Settings();
        public static Settings Settings
        {
            get { return _settings; }
        }
    
            ...
    

    此属性包含应用程序的所有设置。然后绑定看起来像这样:

    "{Binding Source={x:Static local:App.Settings}, Path=LabelsShown}"
    

    编辑:如果您担心依赖关系,您还可以使用其最小接口在任何需要它的类的构造函数中注入对这些设置的引用。

    例如

    public class MyControl : ContentControl
    {
        public interface IMyControlSettings
        {
            public bool LabelsShown { get; set; }
        }
    
        private IMyControlSettings _settings;
    
        public MyControl(IMyControlSettings settings)
        {
            _settings = settings;
            DataContext = _settings; // For easy binding, in most cases you probably do not want to do that since it prevents DataContext inheritance.
        }
    }
    
    public class Settings : Test.MyControl.IMyControlSettings, INotifyPropertyChanged
    {
        public bool LabelsShown { get; set; }
        ...
    }
    

    【讨论】:

    • 效果很好。我也可以将这些设置用于很多其他的东西。谢谢!我也喜欢注射位。这将简化绑定,并使其更清晰。
    【解决方案2】:

    你可以这样做:

    public class MySettings : INotifyPropertyChanged {
        private MySettings() {
        }
    
        private Visibility _labelShown;
        public Visibility LabelShown
        {
            get { return _labelShown; }
            set {
                _labelShown = value;
                // Raise PropertyChanged event for LabelShown
            }
        }
    
        private static MySettings _instance;
        public static MySettings Instance
        {
            get {
                if (_instance == null)
                    _instance = new MySettings();
                return _instance;
            }
        }
    }
    

    然后像{Binding Path=LabelShown, Source={x:Static local:MySettings.Instance}}一样绑定到它

    您唯一需要添加的是本地 xmlns,类似于 xmlns:local="clr-namespace:MyNamespace"

    【讨论】:

      【解决方案3】:

      我发现了一个有点蹩脚的解决方法:

          public static Visibility LabelShown
          {
              get { return _labelShown; }
              set
              {
                  _labelShown = value;
                  if ( StaticEvent != null )
                  {
                      StaticEvent();
                  }
              }
          }
      
          private static event Action StaticEvent;
      
          public event PropertyChangedEventHandler PropertyChanged
          {
              add { StaticEvent += () => value(this, new PropertyChangedEventArgs("LabelShown")); }
              remove { StaticEvent -= () => value(this, new PropertyChangedEventArgs("LabelShown")); }
          }
      

      它有效,但我有点担心删除处理程序实际上能够删除这样的匿名方法。如果释放了许多控件,这会导致内存问题吗?

      我更喜欢 CodeNaked 的解决方案,但我想提供这个供讨论。

      【讨论】:

        猜你喜欢
        • 2010-09-27
        • 2012-05-23
        • 2010-10-30
        • 2014-08-20
        • 1970-01-01
        • 2014-09-10
        • 2020-10-01
        • 2010-12-01
        • 1970-01-01
        相关资源
        最近更新 更多