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?

2
Gilles Radrizzi 15 lipiec 2011, 16:52

3 odpowiedzi

Najlepsza odpowiedź

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ć.

0
Gilles Radrizzi 15 lipiec 2011, 17:32
Myślę, że bardziej sensowne byłoby dodanie właściwości takiej jak BindableSender do klasy częściowej. Po prostu pobierze/ustawi właściwość Sender i uruchomi zdarzenie PropertyChanged. Następnie możesz po prostu powiązać się z tym, na przykład {Binding Path=File.BindableSender.Name}
 – 
Mtihc
27 styczeń 2015, 23:36

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ć.

0
4th Dimension 24 wrzesień 2014, 11:57