Quantcast
Channel: Windows Presentation Foundation (WPF) forum
Viewing all articles
Browse latest Browse all 18858

.Net WPF MVVM TabControl "Setting Focus" to a tab?

$
0
0

I'm developing an MVVM WPF application and have run across another small stumbling block.  In my main application window, I'm using a tabbed control as my MDI.  This tab control is bound to a (observable) collection named OpenWorkspaces, which contains all the "windows" (or Workspaces in my app's language) the user has open.  Here is what a "Workspace" looks like:

    Public Class Workspace

        Private _WorkspaceID As Integer
        Public Property WorkspaceID() As Integer
            Get
                Return _WorkspaceID
            End Get
            Set(ByVal value As Integer)
                _WorkspaceID = value
            End Set
        End Property

        Private _WorkspaceName As String
        Property WorkspaceName As String
            Get
                Return _WorkspaceName
            End Get
            Set(value As String)
                _WorkspaceName = value
            End Set
        End Property

        Private _ViewModelName As String
        Property ViewModelName As String
            Get
                Return _ViewModelName
            End Get
            Set(value As String)
                _ViewModelName = value
            End Set
        End Property

        Private _ViewObjectName As String
        Public Property ViewObjectName() As String
            Get
                Return _ViewObjectName
            End Get
            Set(ByVal value As String)
                _ViewObjectName = value
            End Set
        End Property

        Private _ViewObject As UserControl
        Property ViewObject As UserControl
            Get
                Return _ViewObject
            End Get
            Set(value As UserControl)
                _ViewObject = value
            End Set
        End Property

        Private _CanSupportMultipleInstances As Boolean
        Property CanSupportMultipleInstances As Boolean
            Get
                Return _CanSupportMultipleInstances
            End Get
            Set(value As Boolean)
                _CanSupportMultipleInstances = value
            End Set
        End Property

        Private _CanOpenDisconnectedFromDB As Boolean
        Public Property CanOpenDisconnectedFromDB() As Boolean
            Get
                Return _CanOpenDisconnectedFromDB
            End Get
            Set(ByVal value As Boolean)
                _CanOpenDisconnectedFromDB = value
            End Set
        End Property

    End Class

Here is the Xaml for my TabControl:

<TabControl ItemsSource="{Binding OpenWorkspaces}" SelectedItem="{Binding SelectedTab, Mode=TwoWay}"
                    Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2" BorderThickness="0" BorderBrush="Transparent"
                    HorizontalAlignment="Stretch" VerticalAlignment="Stretch"><TabControl.ItemTemplate><DataTemplate><Grid><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition Width="10"/><ColumnDefinition/></Grid.ColumnDefinitions><TextBlock Text="{Binding WorkspaceName}" Grid.Column="0" Padding="0,1,0,0"/><Button Content="X" Grid.Column="2" 
                                Command="{Binding DataContext.CloseWorkspace, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Mode=TwoWay}"
                                CommandParameter="{Binding}"
                                BorderThickness="0" BorderBrush="Transparent" Background="Transparent" Padding="-4"/></Grid></DataTemplate></TabControl.ItemTemplate><TabControl.ContentTemplate><DataTemplate><UserControl Content="{Binding ViewObject}"/></DataTemplate></TabControl.ContentTemplate></TabControl>

Here is my Execute (from the ICommand) routine bound to my left hand menu buttons (one for each Workspace the user has permission to) which opens a Workspace on Click:

        Public Sub ExecOpenWorkspace(ByVal inWorkspaceName As String)

            'Declare new Workspace variable
            Dim objWorkspace As New Workspace
            Dim exCreatingWorkspace As New CustomException

            'Check to see if this Workspace exists in _OpenWorkspaces
            If CheckForOpenWorkspace(inWorkspaceName) = False Then

                'Attempt to create new workspace and check for an error
                If CreateWorkspaceByName(inWorkspaceName, objWorkspace, exCreatingWorkspace) = 0 Then
                    'Error occurred... set consequence and inform  user of error
                    exCreatingWorkspace.ExceptionConsequence = "Unable to launch form " & inWorkspaceName
                    exCreatingWorkspace.ShowErrorMessage()
                Else
                    'Add inWorkspace to _OpenWorkspaces
                    _OpenWorkspaces.Add(objWorkspace)

                    'Set focus to new tab
                    '???
                End If

            Else

                'Attempt to create the Workspace and check return value
                If CreateWorkspaceByName(inWorkspaceName, objWorkspace, exCreatingWorkspace) = 0 Then
                    'Error occurred... set consequence and show Error
                    exCreatingWorkspace.ExceptionConsequence = "Unable to launch form " & inWorkspaceName
                    exCreatingWorkspace.ShowErrorMessage()
                Else

                    'Need to check to see if this workspace can have multiple instances
                    'open at the same time.
                    If objWorkspace.CanSupportMultipleInstances = True Then
                        'Add the workspace to OpenWorkspaces collection
                        _OpenWorkspaces.Add(objWorkspace)

                        'Set focus to new tab
                        '???
                    Else
                        'Set Focus to the existing Tab
                        '???
                        Debug.Print(_SelectedTab.Header.text)
                    End If

                End If

            End If

        End Sub

I'm not certain if this is relevant to this problem, but here is the code for CreateWorkspaceByName:

        Public Function CreateWorkspaceByName(inWorkspaceName As String, ByRef outWorkspace As Workspace, _
                                              ByRef outException As CustomException) As Integer

            'This routine will attempt to create a new Workspace correlated to the passed in
            'WorkspaceName.
            'The routine will return 1 if it runs successfully, 0 if any error occurs, and will
            'also pass back a workspace object through outWorkspace when successful.

            'Declare variables
            Dim objTempWorkspace As New Workspace
            Dim objViewObject As New Object
            Dim objViewType As Type
            Dim exConnecting As New CustomException

            Try

                'Use LINQ to retrieve the passed in Workspace by Name
                Dim objWorkspace = (From WorkSpace In _AvailableWorkspaces
                                   Where WorkSpace.WorkspaceName = inWorkspaceName
                                   Select WorkSpace).SingleOrDefault

                'Attempt to connect to the database.  Since the Property/Field CanOpenDisconnectedFromDB
                'determines whether a Workspace can be opened without a database connection, we should
                'attempt to connect now before we bother to go through with creating the workspace.

                'Attempt to connect and check for error
                If viewModelMainWindow.CurrentUser.EstablishUserConnection(exConnecting) = 0 Then

                    'No Connection.  Need to check CanOpenDisconnectedFromDB
                    If objWorkspace.CanOpenDisconnectedFromDB = False Then

                        'Set outException to exConnecting
                        outException = exConnecting

                        'Return 0
                        Return 0

                    End If

                End If

                'I want to create a temporary Workspace object to pass back because I believe that if
                'I create a ViewObject (View) for objWorkspace that it will actually store that view
                'with the Workspace objects in _AvailableWorkspaces.  I don't want that to happen...
                'I want the application to close and recreate the ViewObject every time the user
                'closes or opens a form and I also don't want the memory overload of my menu class objects
                'storing Views.
                objTempWorkspace.WorkspaceID = objWorkspace.WorkspaceID
                objTempWorkspace.WorkspaceName = objWorkspace.WorkspaceName
                objTempWorkspace.ViewObjectName = objWorkspace.ViewObjectName
                objTempWorkspace.ViewModelName = objWorkspace.ViewModelName

                'Use GetType to cast object as new View from ViewObjectName field
                objViewType = Type.GetType("CoreTimeClock." & objTempWorkspace.ViewObjectName, True, True)
                objViewObject = Activator.CreateInstance(objViewType)

                'Add objViewObject to objWorkspace
                objTempWorkspace.ViewObject = objViewObject

                'Return objTempWorkspace
                outWorkspace = objTempWorkspace

                'Return 1 to indicate success
                CreateWorkspaceByName = 1

            Catch ex As Exception

                'Return 0 to indicate failure
                CreateWorkspaceByName = 0

                'Set CustomException properties
                outException.IsCustomException = False
                outException.ExceptionObject = ex
                outException.AttemptedAction = "attempting to create form " & inWorkspaceName & "."
                outException.GeneratedBy = "viewModelMainWindow"
                outException.GeneratedByRoutine = "CreateWorkSpaceByName"

                'Log Error
                outException.LogError()

            End Try

        End Function
 

So, if you look at ExecOpenWorkspace, my comments indicate what my problem is.  When I create a new Workspace (which is a TabItem on my TabControl), it gets created just fine, but doesn't get "focus".  Also, I want the result of clicking a button for a Workspace (which can only be opened once) that is already opened to be for it to receive "focus".  On a different form, I was able to do "on demand loading" of the individual tabs of a tab control by binding to "SelectedItem". However, that TabControl isn't dynamic like the one for my main window, which I think makes a big difference because "SelectedItem" always seems to be Nothing.  In other words... my "Debug.Print" line always generates an exception.

Any ideas on how to accomplish setting focus with my dynamic tab control?  As always, thanks in advance for the help!  The guidance I've received from the MSDN community has been absolutely invaluable :).


Viewing all articles
Browse latest Browse all 18858

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>