C# 在单个列表视图中显示多个模型

C# 在单个列表视图中显示多个模型,c#,wpf,linq-to-sql,mvvm,C#,Wpf,Linq To Sql,Mvvm,我有三种型号(联系人、备忘、提醒)。我想搜索所有这些,并在单个listview中生成过滤结果,根据所做的选择,我将在其右侧显示相应的视图(UserControl) 我想要实现设计的正确方法,或者至少是我尝试过的该方法的替代方法。 现在,我已经尝试使用一个集成的ViewModel,它具有三个模型的所有属性 public class IntegratedViewModel { ContactModel _contactModel; NoteModel _noteModel;

我有三种型号(联系人、备忘、提醒)。我想搜索所有这些,并在单个listview中生成过滤结果,根据所做的选择,我将在其右侧显示相应的视图(UserControl)

我想要实现设计的正确方法,或者至少是我尝试过的该方法的替代方法。

现在,我已经尝试使用一个集成的ViewModel,它具有三个模型的所有属性

public class IntegratedViewModel
{
    ContactModel _contactModel;
    NoteModel _noteModel;

    public IntegratedViewModel(ContactModel contactModel)
    {
        _contactModel = contactModel;
    } // similarly for other models also

    public string DisplayTitle    // For displaying in ListView
    {             
        get
        { 
            If(_contactModel != null) 
                return _contactModel.Name; 
            If(_noteModel != null)
                return _noteModel.Title;
        }
    }

    //  All other properties from the three models includin the Name/Title properties for displaying them in the corresponding views(UserControl)
}
现在,我将itemsSource设置为
列表

现在,我必须将视图的可见性绑定到MainViewModel中的某些属性。我尝试使用绑定到ListView的SelectedItem的
SelectedEntity
属性的setter设置bool属性,如
IsContactViewSelected
IsNoteViewSelected

public SelectedEntity
{
  //get
  set
  {
    oldvalue = _selectedEntity;
    _selectedEntity = value;
    // now i find the Type of model selected using `oldvalue.ModelType`
    // where ModelType is a property in the IntegratedViewModel
    // according to the type, i set one of the above bool properties to false
    // and do the same for _selectedEntity but set the property to true
    // so that the view corresponding to the selectedEntityType is visible 
    // and others are collapsed
  }
}

[[这里提到的可见性问题已经解决]]

我坚信MVVM,但我不相信创建视图模型,除非必要。只要模型对象正确支持更改通知,并且视图没有视图状态,就可以直接使用模型对象

这里就是这样。您的ListView可以直接绑定到模型,而不会造成混乱,所以我会这样做

以下是我几年前为解决这个问题所写的内容:

<ListView ItemsSource="{Binding AllSelections}">
  <ListView.View>
    <GridView>

      <!-- First column -->
      <GridViewColumn Header="Title" DisplayMemberBinding="{Binding}">
        <GridViewColumn.CellTemplate>
          <DataTemplate>
            <DataTemplate.Resources>

              <!-- First column content for ContactModel objects -->                  
              <DataTemplate DataType="{x:Type local:ContactModel}">
                <TextBlock Text="{Binding Name}" />
              </DataTemplate>

              <!-- First column content for NoteModel objects -->                  
              <DataTemplate DataType="{x:Type local:NoteModel}">
                <TextBlock Text="{Binding Title}" />
              </DataTemplate>

              ...

            </DataTemplate.Resources>

            <!-- This selects one of the above templates and applies it -->
            <ContentPresenter /> 

          </DataTemplate>
        </GridViewColumn.CellTemplate>
      </GridViewColumn>

      <!-- Second column -->
      <GridViewColumn ...>
        ...
      </GridViewColumn>

    </GridView>
  </ListView.View>
</ListView>

...
...
其中,“AllSelections”是ViewModel中的一个属性,它包含一个ICollection,该ICollection混合了ContactModel、NoteModel和RememberModel对象,并且还实现了INotifyCollectionChanged

这种实现视图的方法非常清晰,可以轻松地自定义各种对象类型的表示


今天,我使用了一个我称之为“祖母绿数据基础”的库,它使得处理基于类的源属性名称更容易:

<!-- First column -->
<GridViewColumn Header="Title"
                DisplayMemberBinding="{edf:ExpressionBinding
                  context is local:ContactModel ? Name : Title}" />

<!-- Second column -->
<GridViewColumn ... />


我希望不久能发布我的库供其他人使用,或者你也可以自己编写。同时,具有多个数据模板的解决方案可以工作,而且比创建视图模型并在其中镜像您的属性要干净得多。

我坚信MVVM,但我不相信创建视图模型,除非在必要时。只要模型对象正确支持更改通知,并且视图没有视图状态,就可以直接使用模型对象

这里就是这样。您的ListView可以直接绑定到模型,而不会造成混乱,所以我会这样做

以下是我几年前为解决这个问题所写的内容:

<ListView ItemsSource="{Binding AllSelections}">
  <ListView.View>
    <GridView>

      <!-- First column -->
      <GridViewColumn Header="Title" DisplayMemberBinding="{Binding}">
        <GridViewColumn.CellTemplate>
          <DataTemplate>
            <DataTemplate.Resources>

              <!-- First column content for ContactModel objects -->                  
              <DataTemplate DataType="{x:Type local:ContactModel}">
                <TextBlock Text="{Binding Name}" />
              </DataTemplate>

              <!-- First column content for NoteModel objects -->                  
              <DataTemplate DataType="{x:Type local:NoteModel}">
                <TextBlock Text="{Binding Title}" />
              </DataTemplate>

              ...

            </DataTemplate.Resources>

            <!-- This selects one of the above templates and applies it -->
            <ContentPresenter /> 

          </DataTemplate>
        </GridViewColumn.CellTemplate>
      </GridViewColumn>

      <!-- Second column -->
      <GridViewColumn ...>
        ...
      </GridViewColumn>

    </GridView>
  </ListView.View>
</ListView>

...
...
其中,“AllSelections”是ViewModel中的一个属性,它包含一个ICollection,该ICollection混合了ContactModel、NoteModel和RememberModel对象,并且还实现了INotifyCollectionChanged

这种实现视图的方法非常清晰,可以轻松地自定义各种对象类型的表示


今天,我使用了一个我称之为“祖母绿数据基础”的库,它使得处理基于类的源属性名称更容易:

<!-- First column -->
<GridViewColumn Header="Title"
                DisplayMemberBinding="{edf:ExpressionBinding
                  context is local:ContactModel ? Name : Title}" />

<!-- Second column -->
<GridViewColumn ... />


我希望不久能发布我的库供其他人使用,或者你也可以自己编写。同时,与创建ViewModel并在其中镜像您的属性相比,使用多个DataTemplates的解决方案更有效、更干净。

首先,我要感谢您提供的解决方案,特别是两件事:1)根据数据类型切换DataTemplate 2)实现公共接口。由于AllSelection应该是多种模型的混合体,所以我为namesake创建了一个接口,只有ID属性。AllSelection现在与listview绑定良好。尽管我两方面都知道,但我们需要有人刺痛我们,以便在正确的情况下使用它。首先,我要感谢您提供的解决方案,特别是两件事:1)根据数据类型切换数据模板2)实现公共接口。由于AllSelection应该是多种模型的混合体,所以我为namesake创建了一个接口,只有ID属性。AllSelection现在与listview绑定良好。尽管我两方面都知道,但我们需要有人刺痛我们,以便在正确的情况下使用它。太棒了,你也是。