单个属性绑定不在手动设置属性时更新

时间:2017-05-13 11:50:53

标签: c# wpf binding singleton

我有一个名为AppContext的Singleton对象(实现INotifyPropertyChanged),里面有IsLogged属性。

public class AppContext : INotifyPropertyChanged {

    private static AppContext instance;

    public AppContext() { }

    public static AppContext Instance {
        get => instance ?? (instance = new AppContext());
    }

    static bool _isLogged = true;

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged([CallerMemberName] string propertyName = null) {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public bool IsLogged {
        get => _isLogged;
        set {
            _isLogged = value;
            Console.WriteLine("islogged = {0}", value);
            OnPropertyChanged();
        }
    }
}

我在StaticResource Application.Resources中存储AppContext,该App.xaml引用文件<Application.Resources> <local:AppContext x:Key="AppContext"/> </Application.Resources> 中的Window

<CheckBox IsChecked="{Binding Source={StaticResource AppContext}, Path=IsLogged}"/>

我有两个不同的IsLogged,其中有相同的复选框声明:

private void Button_Click(object sender, RoutedEventArgs e) {
    AppContext.Instance.IsLogged = !AppContext.Instance.IsLogged;
}

这是我的问题:

当我选中/取消选中两个窗口之一的复选框时,它运行良好(两个复选框保持相同的状态)。

但是,如果我添加一个按钮,在点击时会更改{{1}}的状态,则不会更新复选框。

{{1}}

2 个答案:

答案 0 :(得分:1)

诊断

你的问题的根源在于你的AppContext类并不是一个单独的 - 它有一个允许创建任意数量实例的公共构造函数。这恰好发生了什么 - 这段代码:

<Application.Resources>
    <local:AppContext x:Key="AppContext"/>
</Application.Resources>

创建一个新实例而不是引用(预期)单例实例 - 请注意此代码中没有对AppContext.Instance属性的引用。这个新创建的实例在您的窗口之间共享(因此检查/取消选中工作),但是当您修改AppContext.Instance对象时,您实际上修改的对象不同于您的复选框所绑定的对象。

解决方案

为了修复您的代码,您应该修改您的绑定以使用AppContext.Instance作为来源:

<CheckBox IsChecked="{Binding Source={x:Static local:AppContext.Instance}, Path=IsLogged}"/>

或者,如果您想保留绑定并将单例作为资源,则应修改"AppContext"资源以引用AppContext.Instance属性:

<Application.Resources>
    <x:Static x:Key="AppContext" MemberType="{x:Type local:AppContext}" Member="Instance" />
</Application.Resources>

此外,虽然没有必要解决此问题,但我建议将AppContext构造函数设为私有,以便您遵循单例模式并且不会意外创建新实例。

答案 1 :(得分:0)

问题是,我的媒体资源Instance正在StaticResource文件中App.xaml创建一个不同的实例...

我最后将其添加到App.xaml.cs

static AppContext _context;

public static AppContext Context { 
    get => _context ?? (_context = (AppContext) Current.Resources["AppContext"]);
}

现在我在按钮中使用它:

App.Context.IsLogged = !App.Context.IsLogged;

有了这个,只有一个例子。

但如果你有更好的方法来做到这一点,我很感兴趣:)