[英]Bind multiple views to the same data context (WPF-MVVM)
My question might be dumb but I'm pretty new to WPF and MVVM. 我的问题可能很愚蠢,但我对WPF和MVVM都很陌生。
So let's take the following example: 那么我们来看下面的例子:
I have a contactbook app which displays all contacts using a ObservableCollection<Contact>
in the MainWindow-View. 我有一个联系人应用程序,它使用MainWindow-View中的
ObservableCollection<Contact>
显示所有联系人。
When I press the 'add contact' button a new view opens which has text fields for the user to enter a new contact and a save-button. 当我按下“添加联系人”按钮时,将打开一个新视图,其中包含用于输入新联系人和保存按钮的文本字段。 However when I save the entry it gets saved to a new Collection since I'm not in the same data context (both use the same ViewModel as DataContext).
但是,当我保存条目时,它会保存到新的Collection中,因为我不在同一个数据上下文中(两者都使用与DataContext相同的ViewModel)。
My question is how do I share the ObservableCollection<Contact>
with both views so both views can edit it and use the same collection (ie save new contact in a view and the list in main-view also gets updated)? 我的问题是如何与两个视图共享
ObservableCollection<Contact>
,以便两个视图都可以编辑它并使用相同的集合(即在视图中保存新的联系人,主视图中的列表也会更新)?
A few code snippets: 一些代码片段:
private Contact contact;
private ObservableCollection<Contact> _contacts;
public ContactManager()
{
Contacts = new ObservableCollection<Contact>();
contact = new Contact();
}
public ObservableCollection<Contact> Contacts
{
get { return _contacts; }
set
{
_contacts = value;
RaisePropertyChangedEvent("Contacts");
}
}
public String Anrede
{
get { return contact.Anrede; }
set
{
contact.Anrede = value;
RaisePropertyChangedEvent("Anrede");
}
}
public String Vorname
{
get { return contact.Vorname; }
set
{
contact.Vorname = value;
RaisePropertyChangedEvent("Vorname");
}
}
public String Nachname
{
get { return contact.Nachname; }
set
{
contact.Nachname = value;
RaisePropertyChangedEvent("Nachname");
}
}
public String Adresse
{
get { return contact.Adresse; }
set
{
contact.Adresse = value;
RaisePropertyChangedEvent("Adresse");
}
}
public String Telefonnummer
{
get { return contact.Telefonnummer; }
set
{
contact.Telefonnummer = value;
RaisePropertyChangedEvent("Telefonnummer");
}
}
public ICommand CreateTestContactCommand
{
get { return new DelegateCommand(CreateTestContact); }
}
public ICommand AddNewContactCommand
{
get { return new DelegateCommand(AddNewContact); }
}
private void CreateTestContact()
{
var testContact = new Contact
{
Anrede = "Herr",
Vorname = "Max",
Nachname = "Mustermann",
Adresse = "Mustermannstraße 13",
Telefonnummer = "123456789"
};
Contacts.Add(testContact);
}
private void AddNewContact()
{
Contacts.Add(contact);
}
and the XAMLs: 和XAML:
Main Window: 主窗口:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ContactBook_Test"
xmlns:ViewModels="clr-namespace:ContactBook_Test.ViewModels" x:Class="ContactBook_Test.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="488" Width="533" ResizeMode="NoResize">
<Window.DataContext>
<ViewModels:ContactManager/>
</Window.DataContext>
<Grid>
<Grid.DataContext>
<ViewModels:ContactManager/>
</Grid.DataContext>
<Label Content="Kontaktbuch" HorizontalContentAlignment="Center" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" FontSize="36" FontFamily="Calibri" Width="498"/>
<DataGrid ItemsSource="{Binding Contacts}" AutoGenerateColumns="True" CanUserAddRows="false" HorizontalAlignment="Left" Height="327" Margin="10,69,0,0" VerticalAlignment="Top" Width="498"/>
<Button Command="{Binding CreateTestContactCommand}" Content="Testkontakt hinzufügen" HorizontalAlignment="Left" Margin="198,415,0,0" VerticalAlignment="Top" Width="128"/>
<Button Content="Neuer Kontakt" HorizontalAlignment="Left" Margin="16,31,0,0" VerticalAlignment="Top" Width="87" Click="Button_Click"/>
</Grid>
AddContact: 增加联系人:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ViewModels="clr-namespace:ContactBook_Test.ViewModels" x:Class="ContactBook_Test.Views.AddContact"
mc:Ignorable="d"
Title="AddContact" Height="300" Width="300">
<Window.DataContext>
<ViewModels:ContactManager/>
</Window.DataContext>
<Grid>
<Grid.DataContext>
<ViewModels:ContactManager/>
</Grid.DataContext>
<TextBox HorizontalAlignment="Left" Height="23" Margin="84,46,0,0" TextWrapping="Wrap" Text="{Binding Anrede}" VerticalAlignment="Top" Width="200" />
<TextBox HorizontalAlignment="Left" Height="23" Margin="84,85,0,0" TextWrapping="Wrap" Text="{Binding Vorname}" VerticalAlignment="Top" Width="200"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="84,123,0,0" TextWrapping="Wrap" Text="{Binding Nachname}" VerticalAlignment="Top" Width="200"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="84,163,0,0" TextWrapping="Wrap" Text="{Binding Adresse}" VerticalAlignment="Top" Width="200"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="84,201,0,0" TextWrapping="Wrap" Text="{Binding Telefonnummer}" VerticalAlignment="Top" Width="200"/>
<Button Command ="{Binding AddNewContactCommand}" Content="Speichern" HorizontalAlignment="Left" Margin="107,240,0,0" VerticalAlignment="Top" Width="75"/>
<Label Content="Anrede" HorizontalAlignment="Left" Margin="12,43,0,0" VerticalAlignment="Top"/>
<Label Content="Name" HorizontalAlignment="Left" Margin="12,82,0,0" VerticalAlignment="Top"/>
<Label Content="Nachname" HorizontalAlignment="Left" Margin="12,120,0,0" VerticalAlignment="Top"/>
<Label Content="Adresse" HorizontalAlignment="Left" Margin="12,159,0,0" VerticalAlignment="Top"/>
<Label Content="Telefon" HorizontalAlignment="Left" Margin="12,198,0,0" VerticalAlignment="Top"/>
</Grid>
You should use the same instance of the view model for both views. 您应该为两个视图使用相同的视图模型实例。 Remove this from both views:
从两个视图中删除它:
<Grid.DataContext>
<ViewModels:ContactManager/>
</Grid.DataContext>
The Grid
will inherit the DataContext
from the parent window. Grid
将从父窗口继承DataContext
。 As of now you are creating two instances of the view model in each view. 截至目前,您在每个视图中创建了两个视图模型实例。
Also remove this from the AddContact
view: 同样从
AddContact
视图中删除它:
<Window.DataContext>
<ViewModels:ContactManager/>
</Window.DataContext>
...and set its DataContext
when you open the window: ...并在打开窗口时设置其
DataContext
:
AddContact addContact = new AddContact();
addContact.DataContext = this.DataContext;
addContact.Show():
There are some ways to resolve this: 有一些方法可以解决这个问题:
When you create the AddContact in the Main Window Button_Click, inyect or assign the ViewModel. 在主窗口中创建AddContact时,按钮_Click,inyect或分配ViewModel。 For example:
例如:
AddContact(this.DataContext);
or 要么
new AddContact(){DataContext=this.DataContext);
In a MVVM architecture, you can share information between ViewModels with events, see Sharin variables between different ViewModels 在MVVM体系结构中,您可以在ViewModel与事件之间共享信息,请参阅不同ViewModel之间的Sharin变量
Usually the methods that you use to navigate to a page, permits to send data, for example NavigationService.Navigate 通常,用于导航到页面的方法允许发送数据,例如NavigationService.Navigate
I hope this can help you. 我希望这可以帮到你。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.