UpdateSourceTrigger=PropertyChanged oraz dziwny data binding

0

Cześć!

Piszę już dość długo w WPF z wykorzystaniem MVVM ale spostrzegłem niedawno pewną kwestię, której nie bardzo rozumiem, a która pozwala skrócić trochę kod odpowiedzialny za Data binding.

Wyjaśnię na kontrolce DataGrid gdzie pierwszy raz zauważyłem zjawisko, o którym tutaj chcę napisać.

Mianowicie... Do tej pory kiedy robiłem Data binding do przykladowej kontrolki DataGrid to pisałem to w ten oto sposób:

<DataGrid ItemsSource="{Binding Files}"
	      SelectedItem="{Binding SelectedFile, UpdateSourceTrigger=PropertyChanged}">
private FileModel _selectedFile;

public ObservableCollection<FileModel> Files { get; set; }
public FileModel SelectedFile{
	get { return this._selectedFile; }
	set {
		this._selectedFile = value;
		this.OnPropertyChanged("SelectedFile");
	}
}

Rzecz jasna wszystko ładnie działa: SelectedFile zmienia się w zależności od tego, który wiersz z tabeli zostanie wybrany. Jest OnPropertyChanged() więc każda zmiana jest widoczna.

A teraz to co zauważyłem:
Załóżmy, że to samo co wyżej, zbinduję w ten sposób:

<DataGrid ItemsSource="{Binding Files}"
	      SelectedItem="{Binding SelectedFile}">
public ObservableCollection<FileModel> Files { get; set; }
public FileModel SelectedFile { get; set; }

Wszystko ok? No wygląda ok i działa tylko pytanie czemu? O_o
Dlaczego ilekroć wybiorę wiersz z kontrolki DataGrid to wartość obiektu SelectedFile jest odświeżana POMIMO, braku wykorzystania OnPropertyChanged()?
Nie pytam o brak UpdateSourceTrigger=PropertyChanged w kodzie XAML, bo ten jest ustawiony domyślnie w ten sposób dla niektórych kontrolek i tutaj się nie czepiam ale... przecież wartość SelectedFile nie powinna być odświeżana, a jest! :)

Dlaczego? Toć to nie powinno działać hehe.

0

Powinno działać i działa tak jak trzeba. Domyślnie jest ustawiane w widoku Mode=OneWay co powoduje, że zmiana w widoku ląduje w ViewModelu ale już nie na odwrót.

Od kiedy OnPropertyChanged w ViewModelu odpowiada za aktualizację wartości View->ViewModel?

0

Dobra... To mam taki przykładzik, bo wiedziałem, że ktoś napisze o kierunku przepływu danych.
Bindowanie bool do kontrolki Checkbox.

To działa... są zmiany widoczne w kierunku View->ViewModel:

<CheckBox IsChecked="{Binding IsSelected,UpdateSourceTrigger=PropertyChanged}"/>
public bool IsSelected {
	get { return this._isSelected; }
	set {
		this._isSelected = value;
		this.OnPropertyChanged("IsSelected");
	}
}

Dlaczego więc kiedy zrobię tak...

<CheckBox IsChecked="{Binding IsSelected}"/>
public bool IsSelected {
	get { return this._isSelected; }
	set {
		this._isSelected = value;
		//this.OnPropertyChanged("IsSelected");
	}
}

...to nie działa. Przecież powinno działać analogicznie do kontrolki DataGrid i wybierania SelectecFile.

Od kiedy OnPropertyChanged w ViewModelu odpowiada za aktualizację wartości View->ViewModel?

No właśnie popatrz... myślałem, że rozumiem ten mechanizm ale okazuje się, że nie do końca. Jeżeli jest tak jak mówisz to niedziałający przykład z bool'em powinien działać, a nie działa :) Informacje idą przecież w stronę View->ViewModel.

PS: zawsze robiłem OnPropertyChanged() kiedy zmieniałem dane i jakoś się nie zastanawiałem specjalnie na tym co tutaj się dzieje. Zawsze działało ale teraz chciałem ten mechanizm zrozumieć bardziej dogłębnie i utknąłem.

0
grzesiek51114 napisał(a):

Dlaczego więc kiedy zrobię tak...

<CheckBox IsChecked="{Binding IsSelected}"/>
public bool IsSelected {
	get { return this._isSelected; }
	set {
		this._isSelected = value;
		//this.OnPropertyChanged("IsSelected");
	}
}

...to nie działa. Przecież powinno działać analogicznie do kontrolki DataGrid i wybierania SelectecFile.

Z jakiego powodu twierdzisz że nie działa? Wszystko działa jak natura chciała. Debuger prawdę Ci powie (jeśli wiesz co to i jak tym się posługiwać).

0

Wiem co to jest debuger ;)

Ale kiedy właśnie nie działa. Popatrzcie... zrobiłem projekt, w którym button jest aktywowany kiedy jeden z checkboksów jest zaznaczony. Zauważcie, że kiedy OnPropertyChanged() oraz UpdateSourceTrigger... są dla checkboksa w datagridzie wyłączone to przycisk nie aktywuje się pomimo zaznaczenia checkboksa.

To jest trochę dziwne, bo SelectedItem dla kontrolki DataGrid zmienia się bez tego, a zwykła wartość bool nie. Chciałem właśnie dojść do tego kiedy w końcu używać tych właściwości, a kiedy nie, bo używanie cały czas mija się z celem. Chcę to sobie jakoś usystematyzować, bo okazuje się, że używałem update'ów wiele razy zupełnie niepotrzebnie. Trochę już tych programów w WPF napisałem i teraz trochę zgłupiałem mówiąc szczerze.

Według tego co mówisz powinien przecież działać :)

https://www.sendspace.com/file/fidktw

0

To że w DataTemplate widocznie potrzeba jest ustawienia w widoku UpdateSourceTrigger to nadal nie udowadnia że potrzebujesz do tego wołać OnPropertyChanged by widzieć zmianę po stronie ViewModelu.

Dla jasności. OnPropertyChanged wołasz wtedy kiedy chcesz widzieć zmianę w widoku. Z widoku do ViewModelu samo przylatuje (jeśli oczywiście mu nie ograniczysz tego).

0

Kurcze, muszę to sprawdzić jeszcze jutro, bo teraz piszę z telefonu. Właśnie apropos pierwszego akapitu w Twoim poście, to jeżeli nie wywolam OnPropertyChanged to nie poleci update do kolekcji co pokazuje brak aktywacji buttona. A przecież powinien polecieć. Wiesz... ja też byłem przekonany święcie, że jest tak jak mówisz i wszędzie tak piszą ale... :)

0

Ja chyba wiem o co chodzi... czy to przypadkiem nie jest tak, że aktywacja buttona w komendzie jest zrobiona poprzez niejawny databinding do jego własności IsEnabled? Bo jeśli tak to rzeczywiście konieczne jest wywolanie OnPropertyChanged zeby poszło do buttona info z ViewModelu o zmianie wartości obiektu, który o aktywacji decyduje. To by się zgadzało i wyjasnialo dlaczego zmiana nie była propagowana.

0
grzesiek51114 napisał(a):

Właśnie apropos pierwszego akapitu w Twoim poście, to jeżeli nie wywolam OnPropertyChanged to nie poleci update do kolekcji co pokazuje brak aktywacji buttona.

ta komenda jest tak dziwnie zrobiona że się bez przerwy aktualizuje i sprawdza stan checkboxów. ogólnie kod jest kiepski.

jeszcze raz piszę że w DataTemplate widocznie trzeba użyć UpdateSourceTrigger=PropertyChanged i TYLE. Nic więcej żadnego OnPropertyChanged w ViewModelu nie trzeba żeby w tym przypadku działał binding do ViewModelu.

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