- A+
所属分类:.NET技术
摘要
C/S端软件,左侧导航菜单+右侧页面切换的布局很常见。
这篇文章介绍下使用ContentControl控件和TabControl控件如何实现基础的页面切换。
一、使用ContentControl实现页面切换
页面使用UserControl来实现。
基于MVVM框架的思想,利用数据绑定机制,将控件集合绑定到ContentControl的数据源中。
ViewModel中定义UIElement类型变量和OpenPageCommand触发命令,代码如下:
public class MainViewModel:INotifyPropertyChanged { public event PropertyChangedEventHandler? PropertyChanged; public Dictionary<string, UIElement> PageDict { get; set; } = new Dictionary<string, UIElement>(); public UIElement MainContent { get; set; } public Command OpenPageCommand { get; set; } public MainViewModel() { OpenPageCommand = new Command(OpenPage); } private void OpenPage(object o) { //反射创建 Type type=Assembly.GetExecutingAssembly().GetType("WpfApp1.Pages."+o.ToString()); //避免重复创建UIElement实例 if (!PageDict.ContainsKey(o.ToString())) { PageDict.Add(o.ToString(), (UIElement)Activator.CreateInstance(type)); } MainContent = PageDict[o.ToString()]; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MainContent")); } public void DoCloseCommand(object obj) { Pages.Remove(obj as PageModel); } public ObservableCollection<PageModel> Pages { get; set; } = new ObservableCollection<PageModel>(); public int PageSelectedIndex { get; set; } }
XAML中ContentControl绑定MainContent数据源,代码如下:
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="100"/> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <StackPanel Grid.Column="0"> <Button Content="pageA" Command="{Binding OpenPageCommand}" CommandParameter="PageA" /> <Button Content="pageB" Command="{Binding OpenPageCommand}" CommandParameter="PageB" /> </StackPanel> <ContentControl Grid.Column="1" Content="{Binding MainContent}" > </ContentControl> </Grid>
效果如下
二、使用TabControl切换页面
TabControl控件可以在XAML中直接配置TabItem子控件,但是这种方式不适合工程实践。
更合理的方式是使用数据动态绑定的方式,来实现页面的切换。
TabItem样式改造
TabItem控件有Header属性,还有内容属性。其中Header属性默认为Text文本,实际应用中往往还需要关闭按钮,图标按钮等。
因此TabItem样式需要改造,以增加一个关闭按钮为例。
首先创建一个TabItem实体类PageModel.cs:
public class PageModel { public string Key { get; set; } public string Text { get; set; } public UIElement Content { get; set; } public Command CloseCommand { get; set; } }
XAML中增加样式Resource
<Window.Resources> <StackPanel Orientation="Horizontal" x:Key="headerObject" x:Shared="False"> <TextBlock Text="{Binding Text}"/> <Button Content="X" Command="{Binding CloseCommand}" CommandParameter="{Binding}" /> </StackPanel> <Style TargetType="TabItem"> <Setter Property="Header" Value="{StaticResource headerObject}"/> <Setter Property="Content" Value="{Binding Content}"/> </Style> </Window.Resources>
XAML中TabControl调用:
<TabControl Grid.Column="2" ItemsSource="{Binding Pages}" SelectedIndex="{Binding PageSelectedIndex}"> </TabControl>
ViewModel中使用ObservableCollection集合作为TabItem数据集
public ObservableCollection<PageModel> Pages { get; set; } = new ObservableCollection<PageModel>(); public int PageSelectedIndex { get; set; } public MainViewModel() { OpenPageCommand = new Command(OpenPage); } private void OpenPage(object o) { Type type=Assembly.GetExecutingAssembly().GetType("WpfApp1.Pages."+o.ToString()); //避免重复创建实例 if (!Pages.ToList().Exists(x=>x.Text==o.ToString())) { Pages.Add(new PageModel() { Key = o.ToString(), Text = o.ToString(), Content = (UIElement)Activator.CreateInstance(type), CloseCommand=new Command(DoCloseCommand) }); } PageSelectedIndex = Pages.ToList().FindIndex(x => x.Text == o.ToString()); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PageSelectedIndex")); } public void DoCloseCommand(object obj) { Pages.Remove(obj as PageModel); }
实现效果如下
三、总结
上面两种页面切换的方式,适合工程实践中需要设计单页面应用时使用。