2009-03-09 10 views
52

私の最初の実際のWPFアプリケーション(つまり、私以外の誰かが最初に使用することを意図したもの)を構築中です。 WPFでの作業を行う最善の方法です。これは、かなり新しいEntity Frameworkを使用したかなりシンプルなデータアクセスアプリケーションですが、私はこれらの2つのテクノロジ(WPFとEF)を一緒に使用するための最善の方法をオンラインで多く見つけることができませんでした。そこで私はどのように近づいているのかを捨てて、誰かがより良い提案をしているかどうかを見極めることを考えました。WPFデータバインディングでEntity Frameworkを使用するためのベストプラクティス

  • は、私はSQL Server 2008のEFは、両方はるかに、それは必要以上に複雑で、まだ成熟していないが、LINQのツーSQLは明らかに死んでいるように私を打つとEntity Frameworkのを使用しています私は、MSが重点を置いていると思われる技術を使用するかもしれない。

  • これは単純なアプリケーションなので、別のデータレイヤーを構築するのには適していません。私はデータを取得したい場合は、私はかなり単純なLINQのツーエンティティクエリを使用し、通常ストレート私のコードビハインドから、例えば:

    var families = from family in entities.Family.Include("Person") 
          orderby family.PrimaryLastName, family.Tag 
          select family; 
    
  • LINQのツーエンティティクエリはdoesnのIOrderedQueryable結果を返しますエンティティデータモデルにコードを介して新しいレコードを追加すると、この新しいレコードの存在はLinqクエリを参照するさまざまなコントロールに自動的に反映されません。したがって、私は、基礎となるデータ変更を取得する、のObservableCollectionにこれらのクエリの結果を投げています:

    familyOC = new ObservableCollection<Family>(families.ToList()); 
    
  • 私はなど、ソート、フィルタリングを得ることができるように、私は、その後、CollectionViewSourceにのObservableCollectionをマッピングし、データベースに戻る必要はありません。

    familyCVS.Source = familyOC; 
    familyCVS.View.Filter = new Predicate<object>(ApplyFamilyFilter); 
    familyCVS.View.SortDescriptions.Add(new System.ComponentModel.SortDescription("PrimaryLastName", System.ComponentModel.ListSortDirection.Ascending)); 
    familyCVS.View.SortDescriptions.Add(new System.ComponentModel.SortDescription("Tag", System.ComponentModel.ListSortDirection.Ascending)); 
    
  • 私は、そのCollectionViewSourceにさまざまなコントロールをバインドし、どのような-ない:

    <ListBox DockPanel.Dock="Bottom" Margin="5,5,5,5" 
        Name="familyList" 
        ItemsSource="{Binding Source={StaticResource familyCVS}, Path=., Mode=TwoWay}" 
        IsSynchronizedWithCurrentItem="True" 
        ItemTemplate="{StaticResource familyTemplate}" 
        SelectionChanged="familyList_SelectionChanged" /> 
    
  • 私は、レコード/オブジェクトを追加または削除する必要があるとき、私は手動でエンティティデータの両方から行いますモデル、およびのObservableCollection:

    private void DeletePerson(Person person) 
    { 
        entities.DeleteObject(person); 
        entities.SaveChanges(); 
        personOC.Remove(person); 
    } 
    
  • 私は一般のStackPanelとDockPanelを使用していますが要素を配置するように制御します。グリッドを使用することもありますが、維持するのは難しいようです。グリッドの上部に新しい行を追加する場合は、グリッドによって直接ホストされるすべてのコントロールをタッチして、新しいラインを使用するように指示する必要があります。 Uggh。 (マイクロソフトではDRYのコンセプトを実際には見たことがありません)

  • VS WPFデザイナーを使用してコントロールを追加、変更、または配置することはほとんどありません。 VSに付属しているWPFデザイナーは、あなたのフォームがどのように見えるかを知るのに漠然と役立ちますが、実際にはそうではありません。特に、利用可能なデータにバインドされていないデータテンプレートを使用している場合デザインタイム。 XAMLを編集する必要がある場合、私はそれを人のように取り、手動で行います。

  • 実際のコードのほとんどは、XAMLではなくC#です。私がelsewhereを言及したように、私がまだそれを "考える"ことに慣れていないという事実を除いて、XAMLは、醜い、醜い言葉として私を襲ってしまい、デザイナーやインテリセンスの貧弱なサポートにもなります。デバッグできません。 Uggh。その結果、C#コードビハインドで何かを行う方法を明確に見ることができるときは、XAMLのやり方を簡単に見ることができないので、C#でやっています。WPFページでコードビハインドをほとんど使用しない(イベント処理のために)コードビハインドを使用することはほとんどありませんが、少なくとも私にとっては意味がありません。 C#のようなきれいでクリーンな言語を使用することができ、世界レベルのエディタに近い完璧なエディタを使用することができるときに、なぜ神秘的な構文、驚くほど悪いエディタ、および実質的に型の安全性がない、醜い、インテリセンス、比類のないタイプの安全性?

これは私の所です。助言がありますか?私はこれの大きな部分を欠いていますか?違うやり方について本当に考えなければならないことは何ですか?

+0

vs2010/fw4.0:ItemsSourceはfamilyCVS.View(familyCVSではなく)にバインドする必要があります。 –

答えて

19

あなたはEF

からWPFの懸念を区切るために、リポジトリのパターンを実装する必要が次にあなたが減らすためにジェネリックを使用することができますCollectionViewSourceの処理に対するEFの複雑さ

よく設計されたリポジトリは、コードレベルを下げ、ORMを置換できるようにする必要があります。テスト)

このためのいくつかのアイデアがここに

http://blog.nicktown.info/2008/12/10/using-a-collectionviewsource-to-display-a-sorted-entitycollection.aspx

+0

これは私が見逃していた大きな部分の可能性が高く、価値があるようです。ありがとう。 –

+0

この回答の最後のリンクは現在死んでいます。 – Cylindric

+1

真実ですが、Wayback Machineにはまだコピーがあります(http://web.archive.org/web/20130924230947/http://blog.nicktown.info/2008/12/10/using-a-collectionviewsource- to-display-a-sorted-entitycollection.aspx)(寄付することも考えてください!) – sorrell

4

可能であれば、コードビハインドの代わりにインターフェイスを設計するためにExpression Blendを使用し、Visual Studioデザイナを使用する代わりに、時間を大幅に節約できます。また、xamlの代わりにC#を使用して再考しようとします。あなたが「WPF Way」をやっているなら、Xamlはそれほど醜いわけではありません。しばしば、xamlの代わりにコードを使用する方が簡単だと思うときは、間違ったやり方でWPF/xamlでうまく動作するように再考する必要があるためです。 Xamlはあなたがそれに慣れるとすばらしいです。私はまだあまりにも大きくないエンティティフレームワークを使用しています。私はNHibernateを好む。

+0

XAMLを試してみます。しかし、XAMLエディタが石器時代(Blend !!ではインテリセンスなし)であり、XAML構文がとても面白くないという事実を乗り越えるのは難しいです。 Yeccch。 –

+7

XAMLを編集すると、生のブロッコリーを食べるような気分になります。おそらくそれは私にとっては良いことですが、私は木を食べているように味があります。 –

7

また、ここでToList()を行う必要はないと思います。私は、ObservableCollection()はすでにファミリであるIEnumerableを取ると信じています。 ToListを行い、それをObservableCollectionに渡すと、すべてのレコードを2回ループすると思います。

familyOC = new ObservableCollection<Family>(families.ToList()); 

代わりに、少し速くであるべき、これを試してみてください。

familyOC = new ObservableCollection<Family>(families); 
+0

ありがとうございます。私は別のエラーのトラブルシューティングでそれを追加し、決してそれを取り出した。 –

5

どこから来たのか私は理解しています。このarticle by Josh Smithは私の考え方を変更(または変更を開始)するのに役立ちましたので、WPFが奇妙で妨げになることはなく、難しいフレームワークと見なされるのではなく、WPFの利点をいくつか得ることができました。

1

もう1つのツールは、BindableLINQ

バインド可能なLINQは、データバインディングを追加するLINQの拡張セットと標準LINQに伝播能力を変更する私は私のブログから、このリンクをたどっし、何かを言及したかった

2

を照会することができそれ以外の場合はEFで見つけました。トピックの種類はあるが、完全ではない。

.Includeを使用しているときに、EFで狂ったパフォーマンスの問題が発生しています。 MSは自分のウェブサイトの記事でなぜその理由を説明するので、実際に.Loadメソッドを使用するようにコードのほとんどをシフトし始めました。

私はそれを行う別の方法を見つけることができなかったので、やっかいな作業です...私は自分のメソッドを "IncludeByRoundTrip"という名前で作成しました。それはオブジェクトパスをとり、パス全体がロードされることを保証します。最終的な結果は、舞台裏でincludeを使用する場合と同じですが、オブジェクトグラフのすべてのプロパティでLoadを呼び出すだけです。

このようなメカニズムが存在する場合は、order.Load( "Customer.Address")のようなことに似ています。いずれにしても、私のブログでそれをチェックし、あなたの所見を教えてください。私は他の人がIncludeを使って減速に気づいたかどうか、あなたが状況を攻撃する際に他の方法があるかどうかを知りたいのです。

私の解決策に関する詳細は:http://blog.nicktown.info/2009/07/27/method-to-load-an-entire-object-graph-using-adonet-entity-framework.aspxです。

ご迷惑をおかけして申し訳ございませんが、お返事をお待ちしております。