Ten interfejs, o którym mówisz to u mnie w zasadzie klasa abstrakcyjna Document. Powinienem ją nim zastąpić?
Tak. Nic nie stoi na przeszkodzie, żeby zrobić z tego interfejs z dostępnymi własnościami;
Skoro tak, to każdy VM powinien mieć właściwości odpowiadające za treść na kontrolkach, którą przy otwarciu okna, pobiera z zewnętrznych plików i binduje?
Takie coś możesz spokojnie wrzucić do VM przy czym najlepiej utworzyć metody pobierające dane w ramach jakiegoś serwisu, który będzie obsługiwał większą część reszty. Tak żeby logicznie to się trzymało kupy. Taki serwis możesz np. wstrzyknąć do VM. Można też zrobić do tego osobną klasę etc... Cokolwiek byleby VM pozostał VM czyli klasą udostępniającą własności widokowi, a nie czymś co zawiera w sobie tonę logiki, którą można przecież przenieść do klas serwisowych (service classes)
.
Tutaj miałem na myśli ContentFiller, nie Filter. Taki content filler miałbym wstrzyknąć do VM? Czyli miałoby to postać np. interfejsu IFiller, z którego dziedziczą poszczególne wypełniacze, dla poszczególnego okna, a każdy VM miałby w sobie referencję do obiektu typu IFiller? Czy to zbędne udziwnienie?
Aha. No to coś takiego nie musi być częścią VM, ponieważ steruje to bezpośrednio widokiem aplikacji. Można to wrzucić do eventu odpowiedzialnego za odczytywanie danej wersji językowej Twojego programu. Nie wiem czy mnie dobrze zrozumiesz po tym co napisałem więc posłużę się przykładem: Mam proszę ja Ciebie w swoim programie taki panel, który pokazuje mi aktualnie używane przez użytkownika filtry wyszukiwania. Po prostu gość wdzydza filtr, a informacja o tym jaki to filtr zostaje dodana w GUI w formie nieaktywnego guzika na pasku i w ten sposób user wie, że np. używa kaskadowo ileś tam filtrów (tak... wiem, że chodzi o filler
- to tylko przykład hehe).
Teraz jak obsłużyć taką informację? Bardzo prosto. Mam wewnątrz VM takiego delegata: public delegate void ActivateFilterEventHandler(string filterName);
. Na jego podstawie tworzę sobie event, który będzie się odpalał kiedy user użyje jakiegoś filtru: public event ActivateFilterEventHandler ActivateFilter;
.
Super, teraz np. w komendzie należy zrobić jego wywołanie w momencie kiedy user użyje filtru:
public ICommand UseFilter
{
get
{
return new RelayCommand(
()=>
{
// Some logic...
if(this.ActivateFilter != null) this.ActivateFilter(this.SurnameFilter);
},null);
}
}
Tak odpalony event można obsłużyć w miejscu gdzie sterujemy widokiem czyli... w code-behind:)
this.viewModel.ActivateFilter += (filterName) =>
{
// Pseudo-code:
var button = new Button();
button.Content = filterName;
button.IsEnabled = false;
this.StackPanel.Children.Add(button);
}
Viola! GUI samo się układa. Projektant GUI decyduje w code-behind jakiego użyje sposobu na to, żeby pokazać userowi jakich użył filtrów. Ty jako projektant logiki pod spodem dostarczasz jedynie eventa, który transportuje dla GUI nazwę filtru :) Dlatego taki projektant użyje c-b zamiast XAML
? Odpowiedź jest prosta: ilość nieaktywnych guzików, czy jakichkolwiek kontrolek z nazwą filtru nie jest z góry określona i nie da się tego zrobić przez XAML
. Można do tego napisać sobie fabrykę kontrolek ustawiających filtry w GUI, do wyboru do koloru.
Czy gotowy dokument też jest widokiem? Faktury i umowy będą tak naprawdę templatką, wypełnianą szczególnymi już danymi z poziomu programu.
Dokument też jest widokiem, owszem no, bo jakoś musi zostać wyświetlony ale pod spodem siedzi logika, którą zapewne trzeba będzie wrzucić do modelu.