wpf绑定全局静态变量并且实现变更通知(mvvm)

12 篇文章 2 订阅

照搬代老师的博客,这篇文章能解决一个大问题:单例怎么实现WPF数据绑定。

在实际的开发中,有一些集合或者属性可能是全局的,比如当你做一个oa的时候,可能需要展示所有的人员,这时这个所有的人员列表显然可以作为全局参数,比如这里有一个全局的静态属性UserList。而你在使用mvvm做wpf开发的时候,一般每个view都已经指定好了viewmodel。而viewmodel显然是不包含UserList。这时如果你想在绑定了viewmodel里面绑定UserList给某个ListBox该怎么办呢。首先你可以在你的viewmodel里面定义一个UserList指向全局静态变量的引用,就像下面这样:

public ObservableCollection<User> UserList{ get=>return Global.UserList; }

这是一个方法,但这个方法会让你的viewmodel变得臃肿。实际上wpf是支持静态参数的绑定的,在xaml里面这样写:

ItemsSource="{Binding Source={x:Static local:GlobalData.UserList}}"

或者:

ItemsSource="{x:Static local:GlobalData.UserList}"

这样,当你的任何一个模块,改变了UserList里面的东西,所有前端用到这个列表的,都会收到属性变更通知。

我会建议这个全局静态类写成单例模式的,比如下面这样写:

public class GlobalData : INotifyPropertyChanged
{
    private GlobalData()
    { }
    public static GlobalData Instance { private set; get; } = new GlobalData();
    public event PropertyChangedEventHandler PropertyChanged;
    private string title;
    public string Title
    {
        get => title;
        set
        {
            title = value;
            PropertyChanged?.Invoke(null, 
                new PropertyChangedEventArgs(nameof(Title)));
        }
    }
}

绑定时如下:

Text="{Binding Title, Source={x:Static local:GlobalData.Instance}}"

这样做的好处是,当Title被修改了,前端能够自动修改。
再比如,你要在某个件上绑定System.DateTime.Now,则这么写:

<TextBlock Grid.Row="1" Text="{Binding Source={x:Static 
system:DateTime.Now},StringFormat='yyyy-MM-dd HH:mm:ss '}"/>

当然,要定义一下system:

xmlns:system="clr-namespace:System;assembly=mscorlib"

事实上这种绑定是无意义的,因为Now只是普通的属性,并没有实现属性变更通知,因此你的textblock显示的时间不过是第一次加载的时间。它并不会随着时间的变化而变化。
这里面,source的作用其实就是指定源,通常我们绑定,只需要设定path,比如path=Name或者直接绑定某个属性,比如Text=“{Binding Name}”,这样系统会自动从你设定的DataContext里面找Name这个属性。而如果你指定了Source,系统便不会在你的DataContext里面查找,而是从指定的Source里面查找。因此,假设你的GlobalData里面有一个静态实体(Model),它里面有一个UserList,那么你应该这么写:

ItemsSource="{Binding UserList, Source={x:Static local:GlobalData.Model}}"

上面的单例也可以写成传统的带GetInstance方法的单例方式:

public class GlobalData : INotifyPropertyChanged
{
    private GlobalData()
    { }
    private static GlobalData instance = new GlobalData();
    public static GlobalData GetInstance() => instance;
    public event PropertyChangedEventHandler PropertyChanged;
    private string title;
    public string Title
    {
        get => title;
        set
        {
            title = value;
            PropertyChanged?.Invoke(null, 
                new PropertyChangedEventArgs(nameof(Title)));
        }
    }
}

那么此时绑定的时候要绑定到具体的方法上,如下:

<Window.Resources>
        <ObjectDataProvider ObjectType="{x:Type local:GlobalData}" 
                            MethodName="GetInstance" x:Key="GlobalData"/>
    </Window.Resources>
<TextBlock Text="{Binding Source={StaticResource GlobalData}, Path=Title}"/>

自定义控件绑定会出现失败的情况,这不是单例绑定的问题,而是自定义控件的问题

//这种写法只能应对ViewModel,遇到单例会失败,系统提示在ViewModel中找不到属性
Text="{Binding FeedSpeed,Mode=TwoWay}"
//这种控件就可以应对,具体原理不清除,先照抄代老师的代码解决问题。
Text="{Binding FeedSpeed,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:BladeActionData},Mode=TwoWay}"

————————————————
版权声明:本文为CSDN博主「returnTrue999」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dap769815768/article/details/82149363

WPF MVVM中,要绑定全局变量,可以通过以下几个步骤实现。 首先,在ViewModel层中,创建一个公共静态变量,这个变量就是我们的全局变量。例如,我们创建一个名为GlobalData的类,并在其中定义一个名为Name的全局变量。 ```C# public class GlobalData { public static string Name { get; set; } } ``` 接下来,在需要使用全局变量的ViewModel中,可以直接通过GlobalData.Name来访问和修改全局变量的值。例如,我们创建一个名为MainViewModel的类,并在其中使用全局变量Name。 ```C# public class MainViewModel : INotifyPropertyChanged { private string _name; public string Name { get { return _name; } set { if (_name != value) { _name = value; GlobalData.Name = _name; // 修改全局变量的值 OnPropertyChanged(nameof(Name)); } } } // 其他ViewModel代码... #region INotifyPropertyChanged implementation public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #endregion } ``` 最后,在需要使用全局变量的View中,可以通过绑定ViewModel中的Name属性,来实现全局变量的访问。 ```XAML <Label Content="{Binding Name}" /> ``` 通过以上步骤,我们就成功地实现WPF MVVM中对全局变量的绑定。无论在任何ViewModel中修改全局变量的值,都可以在View中动态显示变化的结果。在这个例子中,我们创建了一个GlobalData类作为全局变量的容器,利用ViewModel与View之间的数据绑定机制,实现全局变量在整个应用程序中的共享和更新。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值