9

Mam ogólną kontrolę, która wyświetla edytor oparty na właściwości type wewnątrz ViewModel. Obecnie jest to realizowane za pomocą Control, ControlTemplate i DataTrigger takiego -ControlTemplate z DataTrigger Vs. DataTemplate z DataTemplateSelector

<Control 
    x:Name="MainControl" 
    Grid.Column="1" 
    TargetUpdated="OnTargetUpdated"> 
     <Control.Style> 
      <Style> 
       <Style.Triggers> 
        <DataTrigger 
         Binding="{Binding Path=EditorType}" 
         Value="{x:Static view:EditorType.Bool}"> 
         <Setter 
          Property="Control.Template" 
          Value="{StaticResource boolTemplate}" /> 
        </DataTrigger> 
        <DataTrigger 
         Binding="{Binding Path=EditorType}" 
         Value="{x:Static view:EditorType.Text}"> 
         <Setter 
          Property="Control.Template" 
          Value="{StaticResource textTemplate}" /> 
        </DataTrigger> 
        <DataTrigger 
         Binding="{Binding Path=EditorType}" 
         Value="{x:Static view:EditorType.Integer}"> 
         <Setter 
          Property="Control.Template" 
          Value="{StaticResource integerTemplate}" /> 
        </DataTrigger> 
        ... 
        .... 
       </Style.Triggers> 
      </Style> 
    </Control.Style> 
</Control> 

Teraz to samo można osiągnąć stosując ContentPresenter, DataTemplate i DataTemplateSelector takiego -

<local:EditorTemplateSelector 
    BoolEditorTemplate="{StaticResource boolTemplate}" 
    TextEditorTemplate="{StaticResource textTemplate}" 
    IntegerEditorTemplate="{StaticResource integerTemplate}" 
    ... 
    .... 
    x:Key="EditorTemplateSelector"> 
</local:EditorTemplateSelector> 

<ContentPresenter 
    ContentTemplateSelector="{Binding Source={StaticResource EditorTemplateSelector}}" 
    Content="{Binding}" 
    TargetUpdated="OnTargetUpdated"> 
</ContentPresenter> 

// Template selector returning appropriate template based on type 

czuję drugie podejście, używając DataTemplateSelector jest lepiej, ale chciałbym się od Ciebie dowiedzieć -

  • Który z nich jest lepszy i dlaczego?

  • Czy wystąpi różnica w wydajności w dwóch?

+0

Z tego co wiem, drugi sposób jest uważany za najlepszą praktykę. Jest również znacznie bardziej czytelny, ponieważ nie zawiera logiki selekcji (która zawsze powinna być zdefiniowana w C#). Jednak jestem również zainteresowany punktem wydajności. –

Odpowiedz

9

Słyszałem, że DataTemplateSelectors nie zaktualizować szablon, jeśli wartość oni w oparciu o zmiany, a to dlatego, że zwykle ich nie używać.

Moja preferowana metoda polega na użyciu DataTemplates.

<MyControl.Resources> 
    <DataTemplate TargetType="{x:Type local:BooleanModel}"> 
     <local:BooleanView /> 
    </DataTemplate> 
    <DataTemplate TargetType="{x:Type local:IntegerModel}"> 
     <local:IntegerView /> 
    </DataTemplate> 
    ... 
</MyControl.Resources> 

Po drugie, jeśli chcę zmienić szablon na podstawie właściwości zamiast typu obiektu, staram się używać DataTriggers. Dzieje się tak, ponieważ jeśli ta właściwość zostanie kiedykolwiek zmieniona, powiadomienie PropertyChange automatycznie powiadomi interfejs użytkownika, że ​​uległa ona zmianie i zaktualizuje szablon. Nie wierzę, że DataTemplateSelectors zrobi to automatycznie. Również wolę widzieć logikę wyboru szablonu w moim XAML, nie ukrywać jej w pliku TemplateSelector, ale to tylko osobiste preferencje.

Ostatnim moim wyborem jest użycie DataTemplateSelector. Prawie nigdy nie używam go w aplikacji WPF, chociaż często robię to w Silverlight, ponieważ nie obsługuje mojej preferowanej metody domyślnego DataTemplates (jeszcze)

Nie jestem świadomy żadnych znaczących różnic w wydajności między tymi dwoma, chociaż Byłbym zainteresowany, gdyby ktoś mógł mi powiedzieć inaczej.

+0

Interesujące, jestem prawie pewien, że pytanie dotyczyło WPF, tylko z ciekawości - czy naprawili niejawne szablony w SL4/5, ponieważ wiem, że nie były one dostępne w wersjach prev. –

+0

@Dmitry Wierzę, że ostatni projekt Silverlight, który zrobiłem, był w wersji 4.0, a niejawne DataTemplates nie działało wtedy. Słyszałem, że działają w wersji 5.0, ale jeszcze tego nie zrobili. – Rachel

+0

+1 dla "DataTemplateSelectors nie aktualizuje szablonu, jeśli wartość jest oparta na chan". Sprawdziłem to i szablon nie aktualizuje się, jeśli zmieni się wartość. dzięki. – akjoshi

3

Masz dwa pytania tutaj :)

  1. Gdzie dokonać decsion w XAML (DataTriggers) lub w kodzie TemplateSelector
  2. Co nadrzędnymi cały Style lub tylko DataTemplate. W pierwszej próbce zastępujesz Style, w drugim - DataTemplate.

Here're moja 2c:

będę trzymać się z wyzwalacze, jak dostaniesz atrakcyjną poziom elastyczności z nich - nowy edytor ceny nowych zasobów i wyzwalacz wszystkim w XAML - co może być lepszego? Istnieje jedno potencjalne zastrzeżenie związane z używaniem DataTrigger - może to spowodować wycieki danych.

Rozmowa o Style vs DataTemplate Wybór I's stick ponownie z Style. To może być nieco cięższe wizualne drzewo mądre, ale da ci ostateczną kontrolę nad wyglądem twoich redaktorów.

W szczególności, niektóre właściwości można zdefiniować tylko na poziomie Style, używając StyleSetters. Zdefiniowanie poziomu @DataTemplate po prostu nie zadziała, ponieważ zawartość nie jest bezpośrednim dzieckiem twojego kontenera kontrolnego (istnieje dodatkowy poziom - kontrola actula). Jeśli nie masz takich właściwości, to również są dobre i prawdopodobnie szybsze (?).

+0

Dzięki Dmitry, możesz podać więcej szczegółów na temat 'DataTrigger powodując wycieki danych "? – akjoshi

+0

@akjoshi - Przepraszam, nie będę w stanie wymyślić dokładnej repro, to raczej spostrzeżenie, widziałem kilka projektów, które odnoszą korzyści po zmniejszeniu liczby wyzwalaczy. –

0

Sugerowałbym, że odpowiedź jest bardziej jedno z, twoim zdaniem, control jest konieczne. Dostajesz całą masę funkcjonalności dzięki control, która nie jest dostępna z DataTemplate. Możesz dodać DependencyProperties, events, functions itp. Ale czy tego potrzebujesz? Jeśli nie, kontrola może być przesadna.