W mojej aplikacji używam EntityFramework, WPF i MVVM i mam problemy z aktualizacją databinding relacji między EntityObjects. Udało mi się zmniejszyć rozmiar mojego problemu do zaledwie kilku linii XAML i mam nadzieję, że ktoś może mi pomóc, ponieważ nadal nie jestem zbyt pewny siebie z EF i MVVM.
W każdym razie, tutaj idziemy z uproszczonym XAML:
<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"/>
Używam ostatnich 3 etykiet do testowania mojego wiązania danych. Zmiana File.SentDate za pomocą DatePicker aktualizuje powiązanie danych do ostatniej etykiety bez problemu.
Teraz plik jest typu EntityObject i ma właściwość SenderId typu GUID. Ma również powiązanie z moimi kontaktami za pośrednictwem właściwości nadawcy. Oczywiście SenderId jest identyfikatorem GUID odpowiedniego obiektu Contact EntityObject, który jest powiązany z plikiem poprzez relację nadawcy. Plik może mieć tylko jednego nadawcę typu Kontakt.
W każdym razie dzieje się tak, że kiedy wybieram innego nadawcę za pomocą pola kombi, etykieta wyświetlająca właściwość File.SenderId jest prawidłowo aktualizowana. Jednak ten z właściwością File.Sender.Name, czyli korzystający z relacji, nie jest aktualizowany.
Zgaduję więc, że jest coś wyjątkowego w aktualizowaniu wiązania danych relacji w EF.
Czy ktoś może zaproponować rozwiązanie tego problemu?
3 odpowiedzi
Niestety Entity Framework nie powiadamia o zmianie właściwości skojarzenia. To jest powód, dla którego Twoje Wiązanie nie działało.
Problem został zgłoszony do firmy Microsoft: http://connect.microsoft.com/VisualStudio/feedback/details/532257/entity-framework-navigation-properties-don-t-raise-the-propertychanged-event
Inne obejście pokazuje przykładowa aplikacja BookLibrary WPF Application Framework (WAF) a>. Klasa Book nasłuchuje zdarzenia AssociationChanged i wywołuje odpowiednie zdarzenie 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");
}
Wygląda na to, że znalazłem rozwiązanie, choć dla mnie to raczej obejście. To nie jest rozwiązanie, którego bym się spodziewał, ale działa.
XAML jest nadal taki sam jak powyżej, z wyjątkiem jednej rzeczy. Zamiast wiązać się z File.Sender.Name, wiążę się z File.SenderName w następujący sposób:
<Label Content="{Binding Path=File.SenderName}" Grid.Row="4"/>
SenderName w tym przypadku jest właściwością obiektu File, który dodałem w częściowej klasie tak:
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);
}
}
Tak więc dzieje się tak, że jeśli właściwość SenderId zostanie zmieniona, każę frameworkowi zaktualizować również właściwość SenderName. Otóż to. Działa jak marzenie. Chociaż nadal nie jestem przekonany, że tak to ma działać.
{Binding Path=File.BindableSender.Name}
Innym obejściem, jeśli chcesz po prostu nadać nazwę, jest pominięcie ToString() dla nadawcy i powiązanie bezpośrednio z nadawcą. To obejście jest dobre, ponieważ przez większość czasu, gdy łączymy dane z właściwością właściwości, robimy to w celu uzyskania „nazwy” obiektu ustawionej jako wartość właściwości. Również ta metoda działa dla podejścia Database First również, jeśli edytujesz pliki tt, aby dodać częściowe do wszystkich definicji klas.
Więc dodajesz plik, który zawiera rozszerzenia ToString twoich Entite i dodajesz w nim coś takiego:
public partial Contacts
{
public override string ToString()
{
return Name;
}
}
Więc możesz związać z danymi
<Label Content="{Binding Path=File.Sender}" Grid.Row="5"/>
Teraz powiązanie danych wykryje, czy nadawca się zmieni, a kiedy to zrobi, wywoła ToString, aby określić, co wyświetlić.
Z drugiej strony, jeśli musisz powiązać się z inną niestandardową właściwością, możesz mieć problemy. Pamiętam, że odniosłem sukces z wykorzystaniem DataContext i szablonów, aby to obejść. Powiążesz się z Sender i użyjesz DataTemplate, aby określić, co wyświetlić.
Podobne pytania
Nowe pytania
wpf
Windows Presentation Foundation lub WPF to podsystem do renderowania interfejsów użytkownika w aplikacjach opartych na systemie Windows.