繁体   English   中英

将可见性绑定到静态属性

[英]Binding visibility to static property

我有一个带有标签的控件,我想基于该控件所有实例的全局菜单项隐藏或显示。 如果单击按钮以隐藏标签,则要隐藏所有标签。

我的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,因为无法从我的静态属性引用非静态属性更改的处理程序。

我觉得这也许不是执行此操作的最佳方法,但是我真的很想一个按钮(比实际控件高很多级别)来驱动所有实例的可见性。

CodeNaked的解决方案可以工作,但是它使用Singleton在进行单元测试时存在缺点。 我更喜欢通过在应用程序根目录只有一个设置实例(即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; }
    ...
}

您可以执行以下操作:

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"

我发现了一种la脚的解决方法:

    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的解决方案,但我想将其提供进行讨论。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM