2013-02-12 71 views
1

我有一个示例MVVM WPF应用程序,并且在为我的动态加载模型创建DataTemplates时遇到问题。让我试着解释一下:动态加载类型的ListBox DataTemplate

我有以下简单的类作为我的模型的一部分,这我加载动态

public class Relationship 
{ 
    public string Category { get; set; } 
    public ParticipantsType Participants { get; set; } 
} 

public class ParticipantsType 
{ 
    public ObservableCollection<ParticipantType> Participant { get; set; } 
} 

public class ParticipantType 
{ 

} 

public class EmployeeParticipant : ParticipantType 
{ 
    public EmployeeIdentityType Employee { get; set; } 
} 

public class DepartmentParticipant : ParticipantType 
{ 
    public DepartmentIdentityType Department { get; set; } 
} 

public class EmployeeIdentityType 
{ 
    public string ID { get; set; } 
} 

public class DepartmentIdentityType 
{ 
    public string ID { get; set; } 
} 

这里是我的视图模型的样子。我创建了一个通用对象Model财产暴露我的模型:

public class MainViewModel : ViewModelBase<MainViewModel> 
{ 
    public MainViewModel() 
    { 
     SetMockModel(); 
    } 

    private void SetMockModel() 
    { 
     Relationship rel = new Relationship(); 
     rel.Category = "213"; 
     EmployeeParticipant emp = new EmployeeParticipant(); 
     emp.Employee = new EmployeeIdentityType(); 
     emp.Employee.ID = "222"; 
     DepartmentParticipant dep = new DepartmentParticipant();    
     dep.Department = new DepartmentIdentityType(); 
     dep.Department.ID = "444"; 
     rel.Participants = new ParticipantsType() { Participant = new ObservableCollection<ParticipantType>() }; 
     rel.Participants.Participant.Add(emp); 
     rel.Participants.Participant.Add(dep);    
     Model = rel; 
    } 

    private object _Model; 
    public object Model 
    { 
     get { return _Model; } 
     set 
     { 
      _Model = value; 
      NotifyPropertyChanged(m => m.Model); 
     } 
    } 
} 

然后我试图创建一个列表框,专门显示参与者集合:

<ListBox ItemsSource="{Binding Path=Model.Participants.Participant}"> 
<ListBox.ItemTemplate> 
    <DataTemplate> 
     <StackPanel> 
      <Expander Header="IdentityFields"> 
      <!-- WHAT TO PUT HERE IF PARTICIPANTS HAVE DIFFERENT PROPERTY NAMES --> 
      </Expander> 
     </StackPanel> 
    </DataTemplate> 
</ListBox.ItemTemplate> 

的问题是:

  1. 我不知道如何创建一个模板,可以处理这两种类型的参与antType,在这种情况下,我可以有EmployeeParticipant或DepartmentParticipant,因此根据它,数据绑定路径将被设置为EmployeeDepartment相应的属性
  2. 我虽然要为每种类型创建一个DataTemplate(例如, x:类型EmployeeParticipant),但问题是我的模型中的类在运行时动态加载,所以VisualStudio会抱怨这些类型在当前解决方案中不存在。

如何在ListBox中表示这些数据,然后如果我的具体类型在编译时不知道,但只在运行时?

编辑:增加我的测试ViewModel类

+0

这里一个相关的问题http://stackoverflow.com/questions/11152401/explicitly-set-wpf-binding-datatype – 2013-02-12 15:49:16

回答

2

仍然可以创建一个DataTemplate为每种类型的,但使用的DataType声明让他们自动解决,您可以创建为每个模板性质的DataTemplateSelector(分配从XAML中的StaticResource开始),可以将传入的数据项转换为基类并检查属性或以其他方式确定在运行时使用哪个模板。将该选择器分配给ListBox.ItemTemplateSelector,您将获得类似DataType会给你的行为。

+0

评估各种选择方案后,我认为你的答案是根据我的要求有什么好做的工作。我只是在我的'ItemTemplateSelector'中检查项目对象类型,并基于它返回一个DataTemplate。根据你的建议,我会用最后的方法更新这个问题。谢谢你的帮助! – 2013-02-12 20:46:41

0

这不是一个好的视图模型。您的视图模型应该以视图为中心,而不是以业务为中心。因此,要从视觉角度处理所有四种情况,然后将业务类连接到该视图模型。


编辑:

工作把你的代码:

<ListBox ItemsSource="{Binding Path=Model.Participants}"> 
<ListBox.ItemTemplate> 
    <DataTemplate> 
     <StackPanel> 
      <Expander Header="IdentityFields"> 
       <TextBlock Text={Binding Id} /> 
       <TextBlock Text={Binding Name} /> 
      </Expander> 
     </StackPanel> 
    </DataTemplate> 
</ListBox.ItemTemplate> 
</ListBox> 

我改变了结合,我认为这是一个错误?

我想创建一个视图模型为参与者:

public class Participant_VM : ViewModelBase 
{ 

    private string _name = string.Empty; 
    public string Name 
    { 
     get 
     { 
      return _name ; 
     } 

     set 
     { 
      if (_name == value) 
      { 
       return; 
      } 
      _name = value; 
      RaisePropertyChanged(() => Name); 
     } 

    private string _id= string.Empty; 
    public string Id 
    { 
     get 
     { 
      return _id; 
     } 

     set 
     { 
      if (_id== value) 
      { 
       return; 
      } 
      _id = value; 
      RaisePropertyChanged(() => Id); 
     } 

    } 
} 
+0

很高兴你提起这件事。我将整个ViewModel类添加到问题中。 – 2013-02-12 16:05:19

+0

当你说'做一个可以从视觉角度处理所有四种情况的课程'时,你的意思是XAML Views @Shomo? – 2013-02-12 16:10:07

0

修改ListBox如下。

 <ListBox ItemsSource="{Binding Model.Participants.Participant}"> 
      <ListBox.Resources> 
       <DataTemplate DataType="{x:Type loc:DepartmentParticipant}"> 
        <Grid> 
         <TextBlock Text="{Binding Department.ID}"/> 
        </Grid> 
       </DataTemplate> 
       <DataTemplate DataType="{x:Type loc:EmployeeParticipant}"> 
        <Grid> 
         <TextBlock Text="{Binding Employee.ID}"/> 
        </Grid> 
       </DataTemplate> 
      </ListBox.Resources> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <StackPanel> 
         <Expander Header="IdentityFields"> 
          <!-- WHAT TO PUT HERE IF PARTICIPANTS HAVE DIFFERENT PROPERTY NAMES --> 
          <ContentPresenter Content="{Binding }"/> 
         </Expander> 
        </StackPanel> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 

编辑: loc表示命名空间,其中DepartmentParticipantEmployeeParticipant都存在。希望你熟悉添加命名空间。

+0

谢谢,正如我所说的,我的模型类型在运行时加载,所以我将无法在设计时使用这些类型。即使我在WPF项目中添加了对模型DLL的引用,它也会添加名称空间:'xmlns:loc =“clr-namespace:; assembly = PIM_SBP.TransactionPolicy”“,但仍然不起作用。我得到:'类型引用cannof找到一个名为DepartmentParticipant的公共类型' – 2013-02-12 18:20:49