ObservalableCollection i Bindings w XAML

0

Cześć,

mam sobie taką kontrolkę w XAML:

        <Picker Title="Wybierz filtr"
                TitleColor="Black"
                ItemsSource="{Binding FilterDict}"
                ItemDisplayBinding="{Binding Name}"
                SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
        </Picker>

Zastanawia mnie jedna rzecz. Mianowicie gdy uzupełniam ObservalableCollection w taki sposób:

public ObservableCollection<DictionaryBase> FilterDict { get; private set; }
.
.
.
var coll = await routeService.GetRouteStatusDictionaryAsync();
foreach (var item in coll)
      FilterDict.Add(item);

to picker wyświetla mi poprawnie listę.

Jednak gdy zrobię to tak:

public ObservableCollection<DictionaryBase> FilterDict { get; private set; }
.
.
.
var coll = await routeService.GetRouteStatusDictionaryAsync();
FilterDict = new ObservableCollection<DictionaryBase>(coll);

picker nie pokazuje żadnego rekordu. Mimo, że w Debug i tutaj i tutaj Kolekcja jest uzupełniona.

Czy ktoś mądrzejszy może mi wyjaśnić różnicę?

2

Jest to spowodowane tym, że Twoja właściwość coll nie powiadamia widoku, że się zmieniła i widok pokazuje Ci stare nieodświeżone dane.
ObservableCollection ma wbudowane powiadamianie przy zmianie ilości elementów w liście, dlatego działa. Aby powiadomić kontrolki powiązane (zbindowane) do właściwości użyj interfejsu INotifyPropertyChanged

    public class MainWindowViewModel : INotifyPropertyChanged
    {

        private IList<string> coll = new ObservableCollection<string>();
        public IList<string> Coll
        {
            get { return coll; }
            set { coll = value; OnPropertyChanged("Coll"); }
        }


        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] String propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

W tym przykłądzie metoda OnPropertyChanged powiadamia kontrolki które są powiązane z włąściwością o nazwie podanej w argumencie, w tym przypadku Coll, że mają odświeżyć widok. Metoda OnpropertyChanged znajduje się zwykle w setterze, dzięki temu wymusza odświeżenie bezpośrednio po zmianie właściwości.

Teraz bez przeszkód możesz napisać:

public ObservableCollection<string> GetData()
        {
            return new ObservableCollection<string>()
            {
                "a",
                "b",
                "c"
            };
        }
myViewModel.Coll = GetData();

Edit:
Pomyliłem się, zamiast coll powinno być FilterDict

1

@gswidwa1: dzięki za wyjaśnienie. Dla pól, które nie są ObservableCollection mam oczywiście tak zrobione, np.:

        public GetRouteListResponseBase SelectedItem
        {
            get
            {
                return selectedItem;
            }

            set
            {
                selectedItem = value;
                OnPropertyChanged("GetRouteListResponseBase");

            }
        }

dla obsługi wybrania itemu.

Myślałem, że ObservableCollection ma to jakby w sobie i coś takiego jest niepotrzebne.

2

Ma w sobie i to jest właśnie klucz. Jak zmieniasz elementy w liście to odświeżanie jest automatyczne. Ale jeżeli zmieniasz instancję listy lub właściwości wewnątrz elementów listy to musisz powiadomić ręcznie.

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