WPF - Bindowanie TextBox z własną klasą

0

Mam problem z bindowaniem z kodu do kontrolki TextBox. Po uruchomieniu programu w polu tekstowym pojawia się wartość zadeklarowana przy tworzeniu obiektu UserContact.City-> "Warszawa". Edycja pola tekstowego powoduje również zmianę w obiekcie.

Problem jest, gdy podczas uruchomionego programu zmieniam wartość UserContact.City np. po kliknięciu w przycisk. UserContact.City zmienia się, ale w polu tekstowym ta zmiana nie jest widoczna.

Dodam, że na formie mam jeszcze inne pola tekstowe oraz listy, które działają prawidłowo. Różnica jest taka, że ich wartości nie są zamknięte w mojej klasie, lecz są to zwykłe obiekty klasy string np. text="{Binding AccountNumber}".

XAML
<TextBox Name="tbCity" Text="{Binding Path=UserContact.City}" Height="24" Width="170" HorizontalAlignment="Left"/>

Próbowałem również:
<TextBox Name="tbCity" Text="{Binding UserContact.City, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="24" Width="170" HorizontalAlignment="Left"/>

CS


    public class ContactData
    {
        public string City { get; set; }
        public string State { get; set; }
        public string Country { get; set; }
        public string PostCode { get; set; }

        public ContactData(string sCity, string sState, string sCountry, string sPostCode)
        {
            City = sCity;
            State = sState;
            Country = sCountry;
            PostCode = sPostCode;
        }
    }

    private ContactData _userContact = new ContactData("Warszawa", "mazowieckie", "Polska", "00-123");
    public ContactData UserContact
        {
            get
            {
                return _userContact;
            }
            set
            {
                if (value != _userContact)
                {
                    _userContact = value;
                    OnPropertyChanged("UserContact");
                }
            }

        }

        private void btnZmien_Click(object sender, RoutedEventArgs e)
        {
            _viewModel.UserContact.City = "Poznan"; // nie zmienia się zawartość pola tekstowego
        }

4

Wydaję mi się, że powinieneś w swojej klasie zaimplementować interfejs INotifyPropertyChanged , który zawiera zdarzenie PropertyChanged. Musisz po prostu zgłaszać to zdarzenie za każdym razem gdy zmieniasz właściwość, która jest powiązana z Twoim polem tekstowym (czyli w tym wypadku chodzi tu chyba o UserContact.City).

0

Interfejs INotifyPropertyChanged mam zaimplementowany w klasie viewModel (obiekt _viewModel). W niej jest zadeklarowany obiekt UserContact klasy ContactData. Dla niej powinienem również implementować interfejs dodatkowo? Zaraz spróbuję.

0

Jak kolega wyżej pisał - musisz zaimplementować interfejs INotifyPropertyChanged lub ewentualnie skorzystać z jakiejś biblioteki gdzie zostało już to zrobione, np. MVVM Light - https://mvvmlight.codeplex.com

0

Interfejs INotifyPropertyChanged musisz zaimplementować dla każdej klasy, której właściwości są powiązane z jakąś "kontrolką"(jak ja nie lubię tego słowa :))

0

W końcu działa :) Trochę rozlazła się zrobiła ta niby prosta klasa, ale najwyraźniej tak musi być. Dzięki za pomoc.

1

nie musi, właściwie są dwie szkoły - jedna mówi że nie powinieneś nigdy bindować do modelu a jedynie do viewmodelu a dla wszystkich propertów zrobić w vm proxy
czyli coś w stylu:

public string UserCity
{
    get { return UserContact.City; }
    set { UserContact.City = value; OnPropertyChanged("UserCity"); }
}

oczywiście zmiany widoczne będą tylko jeżeli zmiany dokonasz przypisując do:

ViewModel.UserCity

a nie do:

ViewModel.UserContact.City

1

w przeciwnym wypadku nie dość że trzeba zaimplementować interfejs INotifyChanged na modelu to jeszcze trzeba dodać obserwatora i routować eventy - wtedy proksowanie propertów nie ma żadnego sensu poza ideologicznym

1 użytkowników online, w tym zalogowanych: 0, gości: 1