我不确定如何在标题中描述我的场景,所以请原谅我糟糕的头衔。
我的情景:
的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>
任何人都可以提供帮助吗?
答案 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