6

ほとんどの WPF/EF チュートリアルでは、1 つのウィンドウでのデータ バインディングのみを扱います。ただし、実際には、データは多くのウィンドウにまたがって表示されます。多くの場合、最初のウィンドウにレコードを表示し、次のウィンドウで関連する詳細を掘り下げます。

したがって、これは私のシナリオにも当てはまります。ここでは、私のデータ構造と UI を確認できます。実際、私は顧客と請求書を扱っていませんが、構造は同じです。(私の具体的な質問は最後にあります。)

データベースのデザインと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 の「ウィンドウ解像度コントロール」のようなものです) しかし、これはあまりユーザーフレンドリーではありません。
4

1 に答える 1

0

よりクリーンな設計は、MVVM 設計パターンを使用することです。

ビュー モデルをウィンドウのコンテキストに挿入し、ビュー モデルをエンティティのコレクションまたは単一のエンティティにバインドし、xaml でビュー モデルのプロパティにバインドし、ビュー モデルに実装されたコマンドをアクションに使用します。 、 消去。

ウィンドウはコンテキストを認識してはなりません。

リスト ビュー モデル + ウィンドウと詳細ウィンドウ (ビュー モデルが望ましい) がある場合、リスト ビュー モデルは、選択された項目をコンテキストとして詳細ビュー モデル (またはウィンドウ) に渡す必要があります。

ウィンドウが同時に開いていないか、関連するオブジェクトがない場合、それらのビュー モデルはデータベース コンテキストを共有すべきではありません。それ以外の場合は、変更がウィンドウ間で簡単に反映されるように、データベースを共有する必要があります。環境。

于 2013-04-21T20:33:43.863 に答える