将可见性绑定到静态属性

时间:2011-04-15 16:31:31

标签: c# wpf binding

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

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

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

3 个答案:

答案 0 :(得分:3)

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

e.g。

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

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

e.g。

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; }
    ...
}

答案 1 :(得分: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"

答案 2 :(得分:0)

我找到了一个有点蹩脚的解决方法:

    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的解决方案,但我想提供这个讨论。