摘要 C/S端軟體,左側導航菜單+右側頁面切換的佈局很常見。 這篇文章介紹下使用ContentControl控制項和TabControl控制項如何實現基礎的頁面切換。 一、使用ContentControl實現頁面切換 頁面使用UserControl來實現。 基於MVVM框架的思想,利用數據綁定機制,將控 ...
摘要
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);
}
實現效果如下
三、總結
上面兩種頁面切換的方式,適合工程實踐中需要設計單頁面應用時使用。
源碼地址https://github.com/cyberneo666/wpf_demo
本文來自博客園,作者:cyberneo666,轉載請註明原文鏈接:https://www.cnblogs.com/cyberneo666/p/16886949.html