具有不同viewmodel -prism的相同视图

时间:2014-05-05 12:15:05

标签: wpf mvvm prism

我不确定如何在标题中描述我的场景,所以请原谅我糟糕的头衔。

我的情景:

的MainView:

 <Grid>
    <TabControl ItemsSource="{Binding Tabs}"
                SelectedIndex="0">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding ViewName}"/>
            </DataTemplate>
        </TabControl.ItemTemplate>
        <TabControl.ContentTemplate>
            <DataTemplate>
                <ContentControl x:Name="SamplesContentControl"
                                Content="{Binding View}"
                                VerticalContentAlignment="Stretch"
                                HorizontalContentAlignment="Stretch"/>
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>
</Grid>

MainViewModel:

public  class MainViewModel
{
   public  List<Tab> Tabs { get; set; }
    IUnityContainer container;
    public MainViewModel(IUnityContainer container)
    { 
        this.container=container;
        Tabs = new List<Tab>();
        Tabs.Add(new Tab() { ViewName = "Test1", View = this.container.Resolve<TestView>() });
        Tabs.Add(new Tab() { ViewName = "Test2", View = this.container.Resolve<TestView>() });
        Tabs.Add(new Tab() { ViewName = "Test3", View = this.container.Resolve<TestView>() });
    }
}

TestView是一个ListView,我希望3个视图有不同的数据。例如,Test1视图具有Test1的数据,Test2View具有Test2的数据。但我不知道如何实现这一目标。

TestViewModel:

 public class TestViewModel
{
    public ObservableCollection<Test> Tests{ get; set; }

    public TestViewModel(ITestDataService testDataService)
    {
        Tests= new ObservableCollection<Test>(testDataService.GetTests());
    }
}

TestView:

  <ListView ItemsSource="{Binding Samples}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="{Binding Title}" Margin="8"/>
                    <TextBlock Text="{Binding Summary}" Margin="8,0,8,8"/>                       
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

任何人都可以提供帮助吗?

2 个答案:

答案 0 :(得分:0)

您可以考虑两个替代方案来解决您提到的问题:

  • 一个简单的解决方法,但不是完全优雅,将重命名 TestView 并创建3个不同的测试视图,其中每个人都知道 ViewModel 会是什么绑定到 DataContext

  • 但是,另一方面,你可以保留一个只有通用的 TestView ,并从 MainViewModel <处理每个实例 DataContext / strong>构造函数。当 MainViewModel 类将所有 TestView 实例添加到 TabList 时,那将是 TestView 实例的> DataContext 。 MainViewModel 将负责创建每个 TestView 以及相应 ViewModel DataContext 的管理员> 观看次数

    因此,您可以解决 TestView 实例,并在NewTab句子之前使用正确的 ViewModel 设置其 DataContext

作为个人意见,第二种方法可能更清洁。特别是如果需要第四个 TestView ,您不需要创建新的查看类型。

<强>更新

关于在 MainViewModel 中设置 DataContext 的第二个解决方案,代码可能如下所示:

public  class MainViewModel
{
   public  List<Tab> Tabs { get; set; }
   IUnityContainer container;
   public MainViewModel(IUnityContainer container)
   { 
       this.container = container;

       TestView view1 = this.container.Resolve<TestView>();
       view1.DataContext = this.container.Resolve<Test1ViewModel>(); 
       TestView view2 = this.container.Resolve<TestView>();
       view2.DataContext = this.container.Resolve<Test2ViewModel>();
       TestView view3 = this.container.Resolve<TestView>();
       view3.DataContext = this.container.Resolve<Test3ViewModel>();

       Tabs = new List<Tab>();
       Tabs.Add(new Tab() { ViewName = "Test1", View = view1 });
       Tabs.Add(new Tab() { ViewName = "Test2", View = view2 });
       Tabs.Add(new Tab() { ViewName = "Test3", View = view3 });
   }
}

正如您所看到的,概念是 MainViewModel 按照问题中的描述创建每个 TestView 的标签,并且还会管理其配置 DataContext 属性。考虑到设置 DataContext 将成为View创建的一部分, MainViewModel 仍将负责完成每个 TestView 的完整创建与其相应的 DataContext

我想澄清一下,在每个 DataContext 上设置的 ViewModel 将是相应的 TestViewModel ,不是 MainViewModel 本身。这样, MainViewModel 将能够使用每个 TestView 的特定设置来解析每个Test实例。

尝试使用通用 ViewModel ,还需要配置每个实例,这将添加更多不洁净的代码,而不仅仅是设置 DataContext 。根据我的理解,最好将每个Test行为封装在具有描述性名称的不同 ViewModels 上,而不是一个通用 ViewModel

我希望我澄清了建议的方法。

问候。

答案 1 :(得分:0)

我不确定我是否100%理解你的问题,但我试一试。

ObservableCollection<Test1Value> data1 = new ObservableCollection<Test1Value>(new Test1Value[]
{
    new Test1Value("Location1", 23.5),
    new Test1Value("Location2", 52.5),
    new Test1Value("Location3", 85.2)

});
ObservableCollection<Test2Value> data2 = new ObservableCollection<Test2Value>(new Test2Value[]
{
    new Machine("Machine1", "OK"),
    new Machine("Machine2", "not OK"),
    new Machine("Machine3", "OK"),
    new Machine("Machine4", "open")
});
CompositeCollection coll = new CompositeCollection();
coll.Add(new CollectionContainer() { Collection = data1 });
coll.Add(new CollectionContainer() { Collection = data2 });
Data = coll;

<ItemsControl ItemsSource="{Binding Data}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.Resources>
        <DataTemplate DataType="{x:Type local:Test1Value}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Name}"/>
                <TextBlock Text=" ("/>
                <TextBlock Text="{Binding MessuredValue}"/>
                <TextBlock Text=")"/>
            </StackPanel>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:Test2Value}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Machine}"/>
                <TextBlock Text=" - "/>
                <TextBlock Text="{Binding Status}"/>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.Resources>
</ItemsControl>

您可以使用1 viewmodel解决此问题,该{{1}}包含不同测试值的不同集合。 通过将它绑定到CompositeCollection,ListView或ItemsControl将为正确的类(模型)选择正确的视图(数据模板)。

在此处查看有关CompositeCollection的更多信息:http://msdn.microsoft.com/en-us/library/system.windows.data.compositecollection.aspx

或者看看如何绑定如何将CollectionContainer绑定到视图模型中的集合?在这里:How do you bind a CollectionContainer to a collection in a view model?

我认为你需要把它转移到prism,但这个概念应该以同样的方式工作...... =)......

HTH