2016-03-08 48 views
1

我有一個MVVM WPF應用程序,用於顯示紙牌遊戲的卡片。我只是將它們顯示在屏幕上,但是對於許多卡片,它們都在可觀察的集合中。但是,卡片都是不同的類型,它們都是從一個基類繼承而來的。每種卡片類型與用戶控件都有自己完全不同的視圖。因此,根據我的經驗,我明白我可以將ItemSource屬性綁定到可觀察集合,但是如何根據我的ItemSource中的項目類型指定使用某些用戶控件?我推理我可以加載所有用戶控制卡,並根據卡類型在轉換器中打開或關閉每個控制器的可見性,但這聽起來對我來說效率極低。任何人有任何想法?如何在XAML WPF窗口中使用動態元素

+0

您聲明每種卡類型的[DataTemplate](https://msdn.microsoft.com/library/ms742521(v = vs.100).aspx)。或者,如果卡片的類型都是相同的,但是在屬性中指定了它們的類型,則可以使用[DataTriggers](http://www.wpf-tutorial.com/styles/trigger-datatrigger-event-trigger/)。 –

回答

2

您正在尋找DataTemplates。例如,假設您有以下類別:

public class MyViewModel 
{ 
    public List<PersonInfo> DataItems { get; } 
    = new List<PersonInfo>() 
     { 
     new AgeInfo() { Age = 25 }, 
     new NameInfo() { Name = 13 } 
     }; 
} 

public abstract class PersonInfo 
{ 
} 

public class AgeInfo : PersonInfo 
{ 
    public int Age { get; set; } 
} 

public class NameInfo : PersonInfo 
{ 
    public int Name { get; set; } 
} 

你可以有一個ItemsControl(或列表框,ListView控件等),根據該項目的數據類型顯示每個項目:

<ItemsControl ItemsSource="{Binding DataItems}"> 
    <ItemsControl.Resources> 

    <!-- Names are edited via textboxes --> 
    <DataTemplate DataType="{x:Type local:NameInfo}"> 
     <StackPanel> 
     <Label>Name:</Label> 
     <TextBox Text="{Binding Name}" /> 
     </StackPanel> 
    </DataTemplate> 

    <!-- Ages are edited via slider --> 
    <DataTemplate DataType="{x:Type local:AgeInfo}"> 
     <StackPanel> 
     <Label>Age:</Label> 
     <Slider Minimum="0" Maximum="150" Value="{Binding Age}" /> 
     </StackPanel> 
    </DataTemplate> 

    </ItemsControl.Resources> 
</ItemsControl> 

放置DataTemplate的位置取決於您,但只要它位於控件的資源層次結構中,就會使用它。

1

用於映射UI創建ResourceDictionary(EI地圖視圖模型模型),並將其註冊

XAML

<ResourceDictionary ..... 
        xmlns:views="clr-namespace:...." 
        xmlns:viewModels="clr-namespace:...." 
        > 

    <DataTemplate DataType="{x:Type viewModels:viewModels1}"> 
     <views:view1 /> 
    </DataTemplate> 

    <DataTemplate DataType="{x:Type viewModels:viewModels2}"> 
     <views:view2 /> 
    </DataTemplate> 

    ... 

</ResourceDictionary> 

C#

public static class ViewsMapping 
{ 
    private static bool _isUIMappingRegistered = false; 

    public static void Register() 
    { 
     if (!_isUIMappingRegistered) 
     { 
      ResourceDictionary MyResourceDictionary = new ResourceDictionary(); 
      MyResourceDictionary.Source = new Uri(".....", UriKind.Relative); 
      Application.Current.Resources.MergedDictionaries.Add(MyResourceDictionary); 
      _isUIMappingRegistered = true; 
     } 
    } 
} 

觀察集合然後換爲ObservableCollection<BaseClass>,所選視圖將顯示派生類視圖。

+0

對於SO的要求,這似乎太過分了。他們不需要在自己的ResourceDictionary中,即使他們不需要將它合併到代碼中,也可以將其添加到應用程序xaml中。 –

+0

嗨馬克,當然,你是對的,解決方案只需要'將ViewModel匹配到視圖',但我仍然認爲最優雅,有序和可維護的解決方案就是我的回答。 –

+0

感謝您對這個答案的輸入!雖然我確實喜歡這個解決方案的簡單性,但是這個項目並沒有創建/處理資源字典的能力。這有點奇怪,但是團隊中的每個成員都具有某些他們可以做的事情,並且創建一個全球資源字典對於這個項目來說是不可能的。 – Chris