简体   繁体   English

将多个视图绑定到同一数据上下文(WPF-MVVM)

[英]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: 有一些方法可以解决这个问题:

Easy way 简单的方法

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);

Events way 事件方式

In a MVVM architecture, you can share information between ViewModels with events, see Sharin variables between different ViewModels 在MVVM体系结构中,您可以在ViewModel与事件之间共享信息,请参阅不同ViewModel之间的Sharin变量

Inyect data on navigation Inyect导航数据

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM