【发布时间】:2018-12-26 11:22:45
【问题描述】:
我将 MainWindowViewModel 绑定到 MainWindow 的 DataContext。 然后我将这个 MainWindowViewModel 初始化为特定的 itemsPageViewModel。
问题是在启动时我看到 itemsPageViewModel 的类名而不是它的内容: Startup
但是,在通过按钮(RelayCommands)切换页面后,同一个 ViewModel 现在会显示其内容: PageSwitched
两个操作都通过相同的代码行:
CurrentPageViewModel = _itemsPageViewModel
它如何产生不同的结果?
代码
MainWindow.xaml
<Window x:Class="ListItemUI.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="ListItemUI" Height="400" Width="600">
<Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="10"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<StackPanel Orientation="Horizontal">
<Button Content="ITEMS" Margin="2" Command ="{Binding SelectItemsPageViewModel}"></Button>
<Button Content="HELP" Margin="2" Command ="{Binding SelectInfoPageViewModel}"></Button>
</StackPanel>
</Grid>
<ContentControl Grid.Row="2" Content="{Binding CurrentPageViewModel}"/>
</Grid>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Windows;
using ListItemUI.InfoPage.ViewModels;
using ListItemUI.ListItemPage.ViewModels;
using ListItemUI.ViewModels;
namespace ListItemUI.Views
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow(IPageFactory itemPageFactory, IPageFactory infoPageFactory)
{
InitializeComponent();
var mainWindowVM = new MainWindowViewModel(itemPageFactory,infoPageFactory);
DataContext = mainWindowVM;
}
}
}
MainWindowViewModel.cs
using System;
using System.Windows.Input;
using ListItemUI.ListItemPage.ViewModels;
namespace ListItemUI.ViewModels
{
public class MainWindowViewModel : ViewModelBase
{
private readonly IListItemUIViewModel _itemsPageViewModel;
private readonly IListItemUIViewModel _infoPageViewModel;
public ICommand SelectItemsPageViewModel { get; }
public ICommand SelectInfoPageViewModel { get; }
public object CurrentPageViewModel
{
get { return _currentPageViewModel; }
set
{
_currentPageViewModel = value;
RaisePropertyChanged(() => CurrentPageViewModel);
}
}
private object _currentPageViewModel;
public MainWindowViewModel(IPageFactory itemsPageFactory, IPageFactory infoPageFactory)
{
_itemsPageViewModel = itemsPageFactory.CreatePage();
_infoPageViewModel = infoPageFactory.CreatePage();
SelectItemsPageViewModel = new RelayCommand(_ =>
{
CurrentPageViewModel = _itemsPageViewModel;
});
SelectInfoPageViewModel = new RelayCommand(_ =>
{
CurrentPageViewModel = _infoPageViewModel;
});
CurrentPageViewModel = _itemsPageViewModel;
}
}
}
ListItemPage.xaml (dataTemplates)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels ="clr-namespace:ListItemUI.ListItemPage.ViewModels">
<DataTemplate DataType="{x:Type viewModels:ItemViewModel}">
<StackPanel>
<TextBlock Foreground="RoyalBlue" FontWeight="Bold" Text="{Binding Path=ItemViewDescription, StringFormat='Group Info = {0}'}"></TextBlock>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:ItemsPageViewModel}">
<StackPanel>
<TextBlock Text ="{Binding Path=Title}"></TextBlock>
<Grid Grid.Column="0" Background="Aquamarine">
<ListBox ItemsSource="{Binding Path=LocalItemViewModels}" Margin="5">
</ListBox>
</Grid>
</StackPanel>
</DataTemplate>
</ResourceDictionary>
App.xaml
<Application x:Class="ListItemUI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ListItemPage/Views/ListItemPage.xaml"></ResourceDictionary>
<ResourceDictionary Source="InfoPage/Views/InfoView.xaml"></ResourceDictionary>
<!--GLOBAL RESOURCES -->
<ResourceDictionary Source="Views/GlobalResources.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
【问题讨论】:
-
将 ContentControl 的内容设置为 ViewModel 不会让它神奇地创建一个控件作为视图。一些 MVVM 框架,如 Caliburn 会自动执行此操作,但这不是标准的 WPF 行为。
-
感谢大家的反馈。我刚刚添加了为我的 viewModel 定义数据模板的缺失文件。我通过另一个 xaml 定义它:这是正确的方式吗?
-
@GiovanniCiandrini 是的,如果引用了字典。
-
@Babbillumpa 是的。它是来自 app.xaml 的参考
-
所以在 App.xaml 里面你有
.... ?
标签: c# wpf xaml mvvm viewmodel