2011-07-15 7 views
2

私のアプリケーションでEntityFramework、WPF、MVVMを使用していて、EntityObjects間のリレーションシップのデータバインディングを更新する際にいくつかの問題があります。私は問題をXAMLのほんの数行に縮小することができました。私はまだEFとMVVMにはあまり自信がないので、誰かが私を助けてくれることを願っています。EF EntityObjectはリレーションシップのデータバインディングを更新しません

はとにかく、ここでは単純化されたXAMLで行く:私は私のデータバインディングをテストするために、最後の3つのラベルを使用してい

<DatePicker Grid.Row="2" Grid.Column="1" 
        SelectedDate="{Binding Path=File.SentDate, 
StringFormat={}{0:dd/MM/yyyy}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
        VerticalAlignment="Center" IsEnabled="{Binding Path=IsEnabled}"/> 

     <ComboBox Grid.Row="3" Grid.Column="1" ItemsSource="{Binding Contacts}" DisplayMemberPath="Name" 
        SelectedItem="{Binding Path=File.Sender, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEditable="True" 
        VerticalAlignment="Center"> 
     </ComboBox> 

     <Label Content="{Binding Path=File.SenderId}" Grid.Row="4"/> 
     <Label Content="{Binding Path=File.Sender.Name}" Grid.Row="5"/> 
     <Label Content="{Binding Path=File.SentDate}" Grid.Row="6"/> 

。 DatePickerを使用してFile.SentDateを変更すると、問題なくデータバインディングが最後のLabelに更新されます。

今すぐFileはEntityObject型で、GUID型のSenderIdプロパティを持ちます。また、Senderプロパティを介して連絡先との関係もあります。 Obserouly、SenderIdは、Sender関係を通じてFileに関連する対応するContact EntityObjectのGUIDです。ファイルには、連絡先タイプの単一の送信者が1人しか存在できません。

とにかく、コンボボックスを使って別の送信者を選択すると、File.SenderIdプロパティを表示するラベルが正しく更新されます。ただし、File.Sender.Nameプロパティを持つプロパティ、つまりreléationshipを使用するプロパティは更新されません。

私はEFで関係のデータバインディングを更新するために特別なことがあると思います。

誰かがこれに対する解決策を提案できますか?

答えて

1

残念ながら、関連プロパティが変更されたとき、Entity Frameworkは通知しません。それがバインディングがうまくいかなかった理由です。

は問題がマイクロソフトに報告されますhttp://connect.microsoft.com/VisualStudio/feedback/details/532257/entity-framework-navigation-properties-don-t-raise-the-propertychanged-event

別の回避策は、WPF Application Framework (WAF)BookLibraryサンプルアプリケーションで示されています。 BookクラスはAssociationChangedイベントをリッスンし、適切なPropertyChangedイベントを発生させます。

public Book() 
{ 
    … 
    LendToReference.AssociationChanged += LendToReferenceAssociationChanged; 
} 

private void LendToReferenceAssociationChanged(object sender, 
     CollectionChangeEventArgs e) 
{ 
    // The navigation property LendTo doesn't support the PropertyChanged event. 
    // We have to raise it ourselves. 
    OnPropertyChanged("LendTo"); 
} 
+0

ありがとう。それが私の愚かさに関係していないことを知りました。これを早期に知っていれば、私の頭を掻き集めるのに数時間を節約できたでしょう:-) –

0

私は解決策を見つけたように見えますが、それは回避策のようです。私は が期待していた解決策ではありませんが、それは機能します。

XAMLは、1つを除いて、上記と同じです。代わりにFile.Sender.Nameへの結合を、私はこのようなFile.SenderNameにバインド:

:この場合

<Label Content="{Binding Path=File.SenderName}" Grid.Row="4"/> 

SENDERNAMEは、私はこのような部分クラスに追加したオブジェクトファイルのプロパティです

public partial class File 
{ 
     public string SenderName 
     { 
      get 
      { 
       if (this.Sender != null) 
       { 
        return this.Sender.Name; 
       } 

       return string.Empty; 
      } 
     } 
protected override void OnPropertyChanged(string property) 
     { 

      if (property == "SenderId") 
      { 
       OnPropertyChanged("SenderName"); 
      } 
      base.OnPropertyChanged(property); 
     } 
} 

したがって、SenderIdプロパティが変更された場合、SenderNameプロパティも更新するようにフレームワークに指示します。それでおしまい。魅力のように動作します。私はまだこれが働くはずであると確信していませんが。

+0

私は、BindableSenderのようなプロパティを部分クラスに追加する方が意味があると思います。 Senderプロパティを取得/設定し、PropertyChangedイベントを発生させます。それでは、 '{Binding Path = File.BindableSender.Name} 'のようにバインドできます。 – Mtihc

0

送信者のToString()を上書きし、送信者に直接バインドするだけの場合の別の回避策があります。この回避策は、プロパティ値として設定されたオブジェクトの「名前」を取得するために、プロパティのプロパティにデータバインディングを行うときのほとんどの場合に便利です。また、このメソッドは、ttファイルを編集してすべてのクラス定義に部分を追加する場合にも、データベースファーストのアプローチにも機能します。

だから、あなたはあなたのEntitesのToStringメソッドの拡張機能を含むようにファイルを追加し、その中にあなたがこのような何かを追加しますので、あなたがあれば今、データバインディングが検出されます

<Label Content="{Binding Path=File.Sender}" Grid.Row="5"/> 

をデータバインドすることができます

public partial Contacts 
{ 
    public override string ToString() 
    { 
     return Name; 
    } 
} 

を送信者が変更されたとき、それが表示されるときにToStringを呼び出して何を表示するかを決定します。

一方、別の非標準プロパティにバインドする必要がある場合は、問題が発生する可能性があります。私はDataContextとテンプレートを使って成功することを覚えています。 Senderにバインドし、DataTemplateを使用して表示する内容を決定します。

関連する問題