3

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

我有以下简化的类作为我的模型的一部分,我正在动态加载

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 来专门显示参与者集合:

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

如果我的具体类型在编译时不知道,但仅在运行时不知道,我怎么能在 ListBox 中表示这些数据?

编辑:添加了我的测试 ViewModel 类

4

3 回答 3

2

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

于 2013-02-12T15:55:38.487 回答
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>

我更改了绑定,我认为这是一个错误?

我将为参与者创建一个 ViewModel:

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);
        }

    }
}
于 2013-02-12T15:58:04.287 回答
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 指的是存在DepartmentParticipantand的命名空间。EmployeeParticipant希望您熟悉添加命名空间。

于 2013-02-12T16:45:45.400 回答