2010-03-08 30 views
14

我有一個視圖模型,其屬性爲Fields,它是ObservableCollection<FieldVM>。在使用該屬性的觀點,我有一個ItemsControl像這樣:Silverlight中的DataTemplate.DataType替代

... 
<ItemsControl ItemsSource="{Binding Fields}" /> 
... 

FieldVM是一個抽象類,通過這樣的類作爲TextFieldVMEnumFieldVM實現。在運行時,這些FieldVM實現將被添加到Fields屬性中,我希望它們在我的視圖中顯示並顯示相關視圖。

在WPF中,這樣做很簡單,我一直都這樣做。你只是這樣做是合適的資源字典,一切都按預期工作:

<DataTemplate DataType="{x:Type vm:TextFieldVM}"> 
    <v:TextFieldView /> 
</DataTemplate> 

<DataTemplate DataType="{x:Type vm:EnumFieldVM}"> 
    <v:EnumFieldView /> 
</DataTemplate> 

現在,在Silverlight中工作的第一次,我希望我可以做同樣的事情,但DataTemplate沒有一個DataType屬性。我很難過。 Silverlight的做法是什麼?

回答

7

使用值轉換器的類型綁定到每個視圖的可見性:

<DataTemplate> 
    <Grid> 
     <v:EnumFieldView 
      Visibilty="{Binding Converter={StaticResource ViewVisibilityConverter}, ConverterParameter=Enum}" /> 
     <v:TextFieldView 
      Visibilty="{Binding Converter={StaticResource ViewVisibilityConverter}, ConverterParameter=Text}" /> 
    </Grid 
</DataTemplate> 

而在ViewVisibilityConverter的的ConvertTo,切換基於所述類型的可見性。

查看它的另一種方法是使用不同類型的值轉換器從Application.Resources返回不同的數據模板。

<ListBox ItemTemplate="{Binding Converter={StaticResource ItemTemplateFactory}"/> 
在ItemTemplateFactory.Convert()

var fieldVM = value as FieldVM; 

switch fieldVM.FieldType: 
{ 
    case "Text": 
     return Application.Current.Resources["TextTemplate"] as DataTemplate; 

    case "Enum": 
     return Application.Current.Resources["EnumTemplate"] as DataTemplate; 

} 
+3

感謝您的建議。它有效,我將它標記爲答案,但這不是一個真正理想的解決方案......它更像是一種醜陋的黑客攻擊。我不禁感到必須有一個更加適合WPF的方式來做到這一點。 – Alex 2010-03-09 14:36:50

+0

我增加了一個可能更漂亮的選項: – 2010-03-09 22:33:31

+0

@Alex:我意識到我已經晚了一年,但是我實現了一個'BooleanVisibility'附加行爲,您可能會感興趣。你可以在這裏找到這篇文章:http://www.executableintent.com/attached-behaviors-part-1-booleanvisibility/。該系列的第2部分有一個帶有附加行爲框架和'BooleanVisibility'實現的代碼示例。 – 2011-03-23 19:51:19

3

Silverlight不具有DataTemplateSelector但我用這個片段...

<ItemsControl.ItemTemplate> 
    <DataTemplate> 
     <client:TemplateSelector Content="{Binding}"/> 
    </DataTemplate> 
</ItemsControl.ItemTemplate> 

這裏是模板選擇:

public class TemplateSelector : ContentControl 
{ 
    protected override void OnContentChanged(object oldContent, object newContent) 
    { 
     base.OnContentChanged(oldContent, newContent); 

     MyObject f = newContent as MyObject; 

     switch (f.MyProperty) 
     { 
      case "Bool": 
      case "String": 
      case "Array": 
      default: 
       ContentTemplate = Application.Current.Resources["MultiSelectDataTemplate"] as DataTemplate; 
       break; 
     } 
    } 
} 
+0

DataTemplateSelector在Silverlight中不可用... 但是我已經看到在Silverlight中實現這個類的一些嘗試。 以下是一個: http://skysigal.xact-solutions.com/Blog/tabid/427/EntryId/1000/Silverlight-a-port-of-the-DataTemplateSelector.aspx – 2010-07-11 05:28:00

+0

DataTemplateSelector不是Silverlight 4的一部分 – Jehof 2010-08-03 09:00:04

+0

您對了。我用另一個片段作爲替換。編輯。 – funwhilelost 2010-08-03 17:22:28

4

變體從邁克爾的第二個選項(因爲我不能直接工作)。

在資源定義一個額外的DataTemplate:

<DataTemplate x:Key="DynamicTemplate"> 
    <ContentPresenter ContentTemplate="{Binding Converter={StaticResource TemplateChooser}}" Content="{Binding}"/> 
</DataTemplate> 

然後使用該數據模板列表框中

<ListBox ItemTemplate="{StaticResource DynamicTemplate}"> 

TemplateChooser必須是IValueConvertor,其中轉換函數接受一個對象,並返回應該用於該對象的DataTemplate。

+0

不是一個完整的答案,而是一個物品控制的好提示。 – 2010-11-02 16:13:49

8

Microsoft Prism library定製DataTemplateSelector實施,注意到類名在DataTemplate中X:鍵:

    <ItemsControl.ItemTemplate> 
        <DataTemplate> 
         <prism:DataTemplateSelector Content="{Binding}" HorizontalContentAlignment="Stretch" IsTabStop="False"> 
          <prism:DataTemplateSelector.Resources> 
           <DataTemplate x:Key="OpenQuestionViewModel"> 
            <Views:OpenQuestionView DataContext="{Binding}"/> 
           </DataTemplate> 

           <DataTemplate x:Key="MultipleSelectionQuestionViewModel"> 
            <Views:MultipleSelectionView DataContext="{Binding}"/> 
           </DataTemplate> 

           <DataTemplate x:Key="NumericQuestionViewModel"> 
            <Views:NumericQuestionView DataContext="{Binding}"/> 
           </DataTemplate> 
          </prism:DataTemplateSelector.Resources> 
         </prism:DataTemplateSelector> 
        </DataTemplate> 
       </ItemsControl.ItemTemplate> 
-4

你試過忽略的數據類型屬性? ,只是寫的是這樣的:

<DataTemplate> 
    <v:TextFieldView /> 
</DataTemplate> 

工作對我來說

+0

「DataType」屬性的用途是允許動態選擇模板 - 使用適用於相應數據類型的模板,並忽略其他模板。在您的答案中,每次都會使用TetxFieldView。 – 2011-11-08 00:57:55

5

的Silverlight 5終於將包含此功能。在此之前,明顯的答案是我見過的更好的方法之一。

+1

...自從Silverlight 5發佈以來,您不再需要這種解決方法。您必須省略{x:Type}位,然而只需指定類型名稱即可。 – 2012-06-18 20:53:21

0

此博客文章http://www.c-sharpcorner.com/Blogs/1937/介紹了什麼看起來像一個很好的自己動手的數據模板選擇僞裝成一個值轉換器。它的優點是不需要安裝棱鏡。

相關問題