如何替换静态ObservableCollection,使其可以在MVVM方式的所有窗口上访问
本文关键字:方式 MVVM 访问 窗口 替换 何替换 静态 ObservableCollection | 更新日期: 2023-09-27 18:26:11
Atm我得到了一个带有静态ObservableCollection的类(somerandomclasss):
public static ObservableCollection<PersonViewModel> thepeoplelist = new ObservableCollection<PersonViewModem>();
然而,我正在将我的项目转换为MVVM,当然这不是填充我所有项目的好方法(主要是列表视图)。我有多个窗口以这种方式使用这个源代码。
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
lsvallthepeople.ItemSource = somerandomclasss.thepeoplelist;
}
列表视图将显示所有具有该信息的人。然而,我敢打赌,这不是MVVM的方式,而且我还没有找到一个在没有公共静态ObservableCollection的情况下工作的好方法,但是有一个窗口,你可以在其中获得一个列表视图,你可以编辑人员,他们在SQL数据库和PersonViewModel中得到更新(它得到了INotifyPropertyChanged)。
如果您需要更多信息,请随时询问:)。
我相信您的问题是,"在MVVM中跨多个视图共享项目列表的最佳方式是什么?"所以我会这样回答这个问题。
假设您有一个服务,它提供了一种获取人员列表的方法。您称之为"PersonViewModel",但可能会将域实体与ViewModel混淆。在MVVM中,您有一个表示UI控件或屏幕的视图。然后您就有了一个ViewModel,它绑定到视图并将视图连接到数据/域模型。ViewModel可以有许多公共属性,View将绑定到这些属性,包括调用服务以从数据模型中填充这些属性的方法。在您的情况下,我会有一个View+ViewModel,而ViewModel有一个类为"Person"的ObservableCollection属性。
下面的代码是对它实际外观的一种解释。并不是所有的东西都实现了。
public class MyViewModel : INotifyPropertyChanged
{
public ObservableCollection<Person> People { get; set; }
public MyViewModel()
{
this.People = new ObservableCollection<Person>();
this.LoadPeople();
}
private void LoadPeople()
{
this.People.Clear();
// Have your logic here that loads the people collection
}
}
至于管理单个列表,我建议将people集合缓存在某种静态类或视图模型可以访问的singleton中。然后上面的LoadPeople方法可以直接从缓存中提取。您甚至可以延迟加载缓存,以便它在第一次访问之前不会发出服务请求。
internal static class SystemContext
{
private static ObservableCollection<Person> _people = null;
public static ObservableCollection<Person> People
{
get
{
if( _people == null )
{
_people = new ObservableCollection<Person>();
// load the list here from a service or something
}
return _people;
}
}
}
因此,在你的ViewModel中,LoadPeople会看起来像这样:
public void LoadPeople()
{
this.People.Clear();
foreach( Person person in SystemContext.People )
{
this.People.Add( person );
}
}
然后,您的UI将看起来像这样:
<ListBox
ItemsSource={Binding Path=People, Mode=OneWay}
SelectedItem={Binding Path=SelectedPerson, Mode=TwoWay}
>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Path=PersonName, Mode=OneWay}" />
<TextBlock Text="{Binding Path=DateOfBirth, Mode=OneWay}" />
<!-- etc -->
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
您可以使用Static
绑定来绑定ItemsSource
,而不是在代码后面手动设置
<ListBox ItemsSource="{Binding Source={
x:Static local:somerandomclasss.thepeoplelist}}" ... />
或者公开从ViewModel返回集合的属性,并绑定到该属性
public class MyViewModel
{
public ObservableCollection<PersonViewModel> PersonList
{
get { return somerandomclasss.thepeoplelist; }
}
...
}
<ListBox ItemsSource="{Binding PersonList}" ... />
您可能应该将其作为一个服务或存储库,将其注入到需要列表的每个视图模型中(作为抽象)。
由于您只想填充此列表一次,因此可以在服务/存储库实现的构造函数中执行此操作,也可以在服务GetList
方法中使用缓存技术。
由于您总是希望将相同的实例传递给每个视图模型,因此您应该使用单例模式,或者如果使用IoC容器,则针对特定实例注册抽象(例如IPeopleRepository
)。
由于这将是一个服务/存储库,您应该返回一个不依赖于表示技术的类型,即IEnumerable<T>
或IList<T>
,并使用它在每个视图模型中创建可观察的集合。