好的,我使用UserControl
s 而不是Page
s 将它们保存在一个窗口中。由于您没有发布任何 XAML,我不知道您的真正需求是什么,但这是我的看法:
MultiPageSample.xaml(“主窗口”):
<Window x:Class="MiscSamples.MultiPageMVVM.MultiPageSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MiscSamples.MultiPageMVVM"
Title="MultiPageSample" Height="300" Width="300">
<UniformGrid Rows="1" Columns="2">
<local:Page1 DataContext="{Binding Page1}"/>
<local:Page2 DataContext="{Binding Page2}"/>
</UniformGrid>
</Window>
代码背后:
public partial class MultiPageSample : Window
{
public MultiPageSample()
{
InitializeComponent();
DataContext = new MultiPageViewModel();
}
}
视图模型:
public class MultiPageViewModel
{
public Page1ViewModel Page1 { get; set; }
public Page2ViewModel Page2 { get; set; }
public MultiPageViewModel()
{
Page1 = new Page1ViewModel();
Page2 = new Page2ViewModel();
Page2.AddNewCommand = new Command(Page1.AddCommand);
}
}
第 1 页:
<UserControl x:Class="MiscSamples.MultiPageMVVM.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ItemsControl ItemsSource="{Binding Commands}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="{Binding}" Content="Click Me!"
Margin="2"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
代码背后:
public partial class Page1 : UserControl
{
public Page1()
{
InitializeComponent();
}
}
第2页:
<UserControl x:Class="MiscSamples.MultiPageMVVM.Page2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Button Content="Add New Command (I Mean Button)"
VerticalAlignment="Center" HorizontalAlignment="Center"
Command="{Binding AddNewCommand}"/>
</UserControl>
代码背后:
public partial class Page2 : UserControl
{
public Page2()
{
InitializeComponent();
}
}
视图模型:
public class Page2ViewModel
{
public Command AddNewCommand { get; set; }
}
命令类(可以在大多数 MVVM 框架上找到)
//Dead-simple implementation of ICommand
//Serves as an abstraction of Actions performed by the user via interaction with the UI (for instance, Button Click)
public class Command : ICommand
{
public Action Action { get; set; }
public void Execute(object parameter)
{
if (Action != null)
Action();
}
public bool CanExecute(object parameter)
{
return IsEnabled;
}
private bool _isEnabled = true;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
}
public event EventHandler CanExecuteChanged;
public Command(Action action)
{
Action = action;
}
}
public class Command<T>: ICommand
{
public Action<T> Action { get; set; }
public void Execute(object parameter)
{
if (Action != null && parameter is T)
Action((T)parameter);
}
public bool CanExecute(object parameter)
{
return IsEnabled;
}
private bool _isEnabled;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
}
public event EventHandler CanExecuteChanged;
public Command(Action<T> action)
{
Action = action;
}
}
结果:
现在,所有这些混乱的解释:
首先,你必须摒弃在代码中操作 UI 元素的传统心态,拥抱MVVM。
WPF 具有非常强大的DataBinding功能,这在古代恐龙框架中是完全没有的。
请注意我如何使用可重用Command
类(这是大多数 MVVM 框架的基本部分)来表示 Page1ViewModel 中的按钮。然后将这些实例Command
添加到 中ObservableCollection
,当元素添加或删除时,它会通知 WPF,因此 UI 会由Binding
.
然后,DataTemplate
定义为ItemTemplate
inItemsControl
的Page1
用于“渲染” 中的每个项目ObservableCollection
。
当我说 WPF 需要一种完全不同的思维方式来工作时,这就是我所指的。这是 WPF 中一切的默认方法。您几乎不需要在程序代码中引用/创建/操作 UI 元素。这就是 XAML 的用途。
另请注意,这可以通过ViewModel
对两个Page
s 使用相同的方式来简化很多,但我故意将它们分开只是为了向您展示这种情况,即您有不同的 ViewModel 直接相互通信。
如果您有任何疑问,请告诉我。