ほとんどの WPF/EF チュートリアルでは、1 つのウィンドウでのデータ バインディングのみを扱います。ただし、実際には、データは多くのウィンドウにまたがって表示されます。多くの場合、最初のウィンドウにレコードを表示し、次のウィンドウで関連する詳細を掘り下げます。
したがって、これは私のシナリオにも当てはまります。ここでは、私のデータ構造と UI を確認できます。実際、私は顧客と請求書を扱っていませんが、構造は同じです。(私の具体的な質問は最後にあります。)
InvoicesWindow で請求書を選択し、[請求書を表示] をクリックします。CustomerWindow が開き、顧客の詳細と請求書が表示されます。適切な請求書が事前に選択されています。CustomerWindow に表示される各請求書に、項目を追加したり編集したりできます。これは、「ItemWindow」と呼ばれる別のウィンドウで行われます。DataGrid の編集はオプションではありません。それらは読み取り専用に設定されています。
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();
}
}
お客様窓口:
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();
}
}
アイテム ウィンドウ:
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);
}
}
私は思いつきでコードを書きました。そのため、一部のキャストが欠落しており、一部のメソッドのスペルが間違っている可能性があります。「ObjectSet」で正しいタイプを取得したことを願っています。「ObjectCollection」などでもかまいません。
XAML は、次のビデオのように VS2010 の支援を受けて広く作成されました: http://msdn.microsoft.com/de-de/data/ff806174.aspx
それで、最後に私の質問;)
- 施したバインディングのデザインは正しいですか?
- CustomerWindow で、新しいコンテキストを作成します。
- CustomerWindow と ItemWindow の間で、同じコンテキストのデータを渡し、現在のアイテムを手動で選択するだけです。
- CustomerWindow では、customersCollectionViewSource のソースとして単一のエントリを持つ ObjectSet (または ObjectCollection、もう型についてはわかりません) を使用します。これはうまくいきます。ただし、1 つの Customer しか編集しないため、コレクションは必要ありません。単一の顧客をソースとして設定できませんでした。VS2010で生成されたビューソースの調整方法がわかりませんでした。
- 保存はまだしていません。しかし、CustomerWindow と ItemWindow の間の設計が原因で、問題が発生すると思います。ここで何かアドバイスをいただけるかもしれません。
- ItemWindow の「Apply」ボタンが押されると、DB で Item データが更新されます。ただし、その下にある CustomerWindow の Customer および Invoices 関連のデータは除きます。
- ItemWindow を閉じると、CustomerWindow の項目の DataGrid が更新されます。ただし、ItemWindow を開く前にデータが変更されている可能性があるため、CustomerWindow の残りのフィールドはそうではありません。
- その「同期の問題」を克服するための唯一の解決策: ユーザーは、変更があった場合、「新しいアイテム」または「アイテムの編集」を押す前に、CustomerWindow で「適用」を押す必要があります。(2 台のモニターで作業するときの Windows 7 の「ウィンドウ解像度コントロール」のようなものです) しかし、これはあまりユーザーフレンドリーではありません。