This demonstrates how to dynamically load content as different tabs of a tab control are selected, using the MVVM model. The host page has a tab control and a frame. As different tabs are selected, different pages are loaded into the frame area. I did this to simplify and speed up a massive page with six unrelated tabs that has over a thousand properties. It has become too cumbersome, so I looked for a way to split the code up.
Start by creating a Visual Basic WPF project.
Let's start with the content that will be displayed. Add a Page called Page1.xaml and make the content a textblock with the words "This is page 1". The xaml looks like this...
<Page x:Class="Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:PagePerTab"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="Page1">
<Grid>
<TextBlock Text="This is page 1"/>
</Grid>
</Page>
Now open MainWindow.xaml. We will set the DataContext to point to the code behind and define a tab control and a frame.
<Window x:Class="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"
xmlns:local="clr-namespace:PagePerTab"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TabControl Grid.Row="0" ItemsSource="{Binding Tabs}" SelectedItem="{Binding SelectedTab}" Height="25"/>
<Frame Grid.Row="1" Source="{Binding FrameSource}" NavigationUIVisibility="Hidden"></Frame>
</Grid>
</Window>
The tab control is bound to a list of strings and the selected item is bound to a string property. The height is set to 25 to collapse the content area. If you know a better way of doing this, drop me a comment.
The rest of the window contains the frame that hosts the desired page. I have turned off the navigation buttons and bound the FrameSource to a URI property.
The code behind looks like this. Most of it is simply defining the properties that are used by the XAML. The only really interesting line of code is the one that sets FrameSource.
Imports System.ComponentModel
Class MainWindow
Implements INotifyPropertyChanged
Private _Tabs As New List(Of String) From {"Page1", "Page2"}
Private _SelectedTab As String
Private _FrameSource As Uri
Public Property Tabs As List(Of String)
Get
Return _Tabs
End Get
Set(value As List(Of String))
_Tabs = value
NotifyPropertyChanged("Tabs")
End Set
End Property
Public Property SelectedTab As String
Get
Return _SelectedTab
End Get
Set(value As String)
_SelectedTab = value
NotifyPropertyChanged("SelectedTab")
FrameSource = New Uri(SelectedTab & ".xaml", UriKind.Relative)
End Set
End Property
Public Property FrameSource As Uri
Get
Return _FrameSource
End Get
Set(value As Uri)
_FrameSource = value
NotifyPropertyChanged("FrameSource")
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public Sub NotifyPropertyChanged(PropertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(PropertyName))
End Sub
End Class
No comments:
Post a Comment