使用WPF/Entity Framework跨多个窗口进行数据绑定?是否传递上下文?

One*_*rld 6 data-binding wpf entity-framework entity-framework-4

大多数WPF/EF教程仅涵盖一个窗口中的数据绑定.但是,实际上数据会在许多窗口中显示.您经常在第一个窗口中显示记录,并在下一个窗口中深入挖掘相关详细信息.

所以,在我的场景中也是如此.在这里你可以看到我的数据结构和ui.实际上我不是在处理客户和发票,但结构是一样的.(我的具体问题在最后.)

数据库设计和ui模型

在InvoicesWindow中,我可以选择一个发票并按"显示发票".这将打开CustomerWindow,显示客户详细信息及其发票.正确的发票已预先选定.对于CustomerWindow中显示的每个发票,我可以添加项目或编辑它们.这是在一个名为"ItemWindow"的分隔窗口中完成的.编辑DataGrids不是一个选项.它们设置为ReadOnly.

这是wpf-window类的代码(我只是显示了数据,而不是保存):

发票窗口:

public partial class InvoicesWindow : Window 
{ 
    private MyEntities context = new MyEntities();

    public InvoicesWindow () 
    { 
        InitializeComponent(); 
    }

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
        CollectionViewSource invoicesViewSource = (CollectionViewSource)FindResource("invoicesViewSource");
        invoicesViewSource.Source = context.Invoices;
    }

    private void ShowInvoice_Click(object sender, RoutedEventArgs e) 
    { 
        Invoice selectedInvoice = (Invoice)InvoicesDataGrid.SelectedItem; 
        var customerWindow = new CustomerWindow(selectedInvoice);
        customerWindow.ShowDialog();
    }
} 
Run Code Online (Sandbox Code Playgroud)

客户窗口:

public partial class CustomerWindow : Window 
{ 
    private MyEntities context = new MyEntities();
    private Invoice selectedInvoice;

    public CustomerWindow() 
    { 
        InitializeComponent(); 
    }

    public CustomerWindow (Invoice selectedInvoice) 
    { 
        InitializeComponent(); 
        this.selectedInvoice = selectedInvoice;
    }

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
        //Set the data 
        CollectionViewSource customerViewSource = (CollectionViewSource)FindResource("customerViewSource ");
        customerViewSource.Source = context.Customers.Where(p => p.id == selectedInvoice.Customer.id);

        //Select the right invoice
        CollectionViewSource customerInvoicesViewSource = (CollectionViewSource)FindResource("customerInvoicesViewSource ");
        customerInvoicesViewSource.Items.MoveCurrentTo(((ObjectSet<Invoice>)customerInvoicesViewSource.Source).Where(p => p.id == selectedInvoice.id).SingleOrDefault());
    }

    private void EditItem_Click(object sender, RoutedEventArgs e) 
    { 
        Item selectedItem = (Item)ItemsDataGrid.SelectedItem; 
        var itemWindow = new ItemWindow((IQueryable<Customer>)(customerViewSource.Source),selectedInvoice,selectedItem);
        itemWindow.ShowDialog();
    }
} 
Run Code Online (Sandbox Code Playgroud)

项目窗口:

public partial class ItemWindow : Window 
{ 

    private Invoice _selectedInvoice;
    private Invoice _selectedItem;
    private IQueryable<Customer> _customers;

    public ItemWindo() 
    { 
        InitializeComponent(); 
    }

    public ItemWindow(IQueryable<Customer> customers, Invoice selectedInvoice, Item selectedItem) 
    { 
        InitializeComponent(); 
        this._customers = customers;
        this._selectedInvoice = selectedInvoice;
        this._selectedItem = selectedItem;
    }

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
        //Set the data 
        CollectionViewSource customerViewSource = (CollectionViewSource)FindResource("customerViewSource");
        invoicesViewSource.Source = _customers;

        //Select the right invoice
        CollectionViewSource customerInvoicesViewSource = (CollectionViewSource)FindResource("customerInvoicesViewSource ");
        customerInvoicesViewSource.Items.MoveCurrentTo(_selectedInvoice);

        //Select the right item
        CollectionViewSource customerInvoicesItemsViewSource = (CollectionViewSource)FindResource("customerInvoicesItems");
        customerInvoicesItems.Items.MoveCurrentTo(_selectedItem);
    }

} 
Run Code Online (Sandbox Code Playgroud)

我在脑海里写了代码.所以,也许有些演员表缺失了,而且有些方法拼写错误.我希望我用"ObjectSet"得到正确的类型,它也可以是"ObjectCollection"或类似的东西.

XAML是在VS2010的帮助下广泛创建的,就像在这个视频中一样:http://msdn.microsoft.com/de-de/data/ff806174.aspx

所以,最后我的问题;)

  • 我应用的绑定设计是否正确?
    • 在CustomerWindow中,我创建了一个新的上下文.
    • 在CustomerWindow和ItemWindow之间,我只传递相同上下文的数据并手动选择当前项.
    • 在CustomerWindow中,我使用ObjectSet(或ObjectCollection,我不再确定该类型),只有一个条目作为customersCollectionViewSource的Source.这很好用.但是,不需要集合,因为我只编辑单个客户.我没有设法将一个Customer设置为Source.我不知道如何调整VS2010生成的视图源.
  • 我还没有保存.但我认为由于我在CustomerWindow和ItemWindow之间的设计,我会遇到问题.也许你可以在这里给我一些建议.
    • 当按下ItemWindow中的"Apply"-Button时,应该在DB中更新Item数据.但不是CustomerWindow下面的客户和发票相关数据.
    • 关闭ItemWindow时,CustomerWindow中的Items的DataGrid应该更新.但不是CustomerWindow中的其他字段,因为在打开ItemWindow之前可能已经更改了数据.
    • 我唯一能够克服"同步问题"的解决方案:如果有任何更改,用户必须按下"新项目"或"编辑项目"之前在CustomerWindow中按"应用".(有点像使用两个显示器时Windows 7的"窗口分辨率控制")但这不是太用户友好.

Dan*_*rod 0

更简洁的设计是使用 MVVM 设计模式。

将视图模型注入到窗口的上下文中,并将视图模型绑定到实体集合或单个实体,在 xaml 中绑定到视图模型中的属性,并使用视图模型中实现的命令来执行操作,例如添加新的, 删除。

窗口不应该知道上下文。

如果您有一个列表视图模型+窗口和一个详细信息窗口(最好带有视图模型),则列表视图模型应将所选项目作为上下文传递给详细信息视图模型(或窗口)。

如果窗口不同时打开或没有相关对象,则它们的视图模型不应共享数据库上下文,否则,为了使更改能够在窗口之间轻松反映,它们将必须共享数据库语境。