WPF 绑定到系统:布尔值未更新

本文关键字:布尔值 更新 系统 绑定 WPF | 更新日期: 2023-09-27 18:36:05

我需要时不时地更新资源值,但是绑定没有更新,如何实现 Notify 方法?

这就是我使用计时器更新资源的方式,CheckInternet.Status 返回一个布尔值。

_timer.Tick += (sender, args) =>
            {
                if (t < 10)
                {
                    t++;
                }
                else
                {
                    Application.Current.Resources["InternetConnected"] = new CheckInternet().Status;
                    t = 0;
                }
                CurrentTime = DateTime.Now.ToLongTimeString();
            };

假设我需要类似以下内容的东西,但是我真的不想添加要绑定到的其他属性,我是否可以只创建一个 NotifyBoolean 的实例并设置和取消设置值并通知更新而不需要其他属性?

public class NotifyBoolean : Common.NotifyUIBase
    {
    }

编辑 - 绑定

<TextBlock Text="{Binding Source={StaticResource InternetConnected}, Converter={StaticResource BooleanToStringConverter}, StringFormat=Internet: {0}}" />

WPF 绑定到系统:布尔值未更新

ResourceDictionary 不会

在更改资源时引发任何事件,一般来说,您不会将资源用于此目的。通常,资源用于您想要创建一次并共享的内容,例如样式或图像、画笔等内容。我什至会说,你通常不想在你的ResourceDictionary里放一些可能在某个时候改变的东西。

建议:使用INotifyPropertyChanged

WPF 依赖于两个用于更改通知的接口:对于属性,您需要实现INotifyPropertyChanged 。对于集合,实现INotifyCollectionChanged(或者更简单地说,只需使用 ObservableCollection<T> ,它会为您处理所有内容)。

所以你创建了一个类:

public class CheckInternetModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private bool m_InternetConnected;
    public bool InternetConnected
    {
        get { return m_InternetConnected; }
        set
        {
            m_InternetConnected = value;
            OnPropertyChanged();
        }
    }
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

您可以将其设置为控件的DataContext,并将绑定更改为 {Binding InternetConnected}

如果确实要使用资源,可以将此类的实例添加到资源中:

<Window.Resources>
    <vm:CheckInternetModel x:Key="CheckInternetModel"/>
</Window.Resources>

您的绑定成为...

<TextBlock Text="{Binding InternetConnected Source={StaticResource CheckInternetModel}, Converter={StaticResource BooleanToStringConverter}, StringFormat=Internet: {0}}" />

您的timer.Tick变成...

((CheckInternetModel)Application.Current.Resources["CheckInternetModel"]).InternetConnected = new CheckInternet().Status;

解决办法:手动使绑定失效

如果您坚持将其作为布尔值存储在资源字典中,剩下的唯一解决方案是使用 DependencyObject.InvalidateProperty 手动使绑定失效。因此,您必须为TextBlock命名,然后从timer.Tick处理程序中添加:

textBlock.InvalidateProperty(TextBlock.TextProperty);

但这还不够。您的绑定是StaticResource,因此它不会查询ResourceDictionary以再次获取资源。必须将绑定更改为:

<TextBlock Text="{Binding Source={DynamicResource InternetConnected}, Converter={StaticResource BooleanToStringConverter}, StringFormat=Internet: {0}}" />

DynamicResource强制绑定在每次请求资源时再次查找资源,因此当您使TextProperty无效时,它将再次从字典中检索InternetConnected,并且它将具有新值。