Link to home
Start Free TrialLog in
Avatar of Dnx_7
Dnx_7Flag for Belgium

asked on

How to mix winform and wpf

Hi experts,

I have a DLL that contains usercontrols in winforms and wpf
i have a winform that host those usercontrols

the way i load the usercontrols is reflection

activator.createinstance...

With Winform usercontrol, i have no problem but with wpf, i did a trick to create wpf usercontrol via reflection by launching it in another thread and set apartment state to STA...

by the way, every controls are created (win and wpf) all events are linked to methods between them too

but when the host forms load...

i have this error :

The calling thread cannot access this object because a different thread owns it.


MAIN CODE : 

        <STAThread()> _
        Sub Main()

            With _thread
                .SetApartmentState(ApartmentState.STA)
                .Priority = ThreadPriority.Normal
                .Start()
            End With

        End Sub

        Private Sub Run()

            Context = New MyContext(New Login)
            Application.EnableVisualStyles()
            Application.Run(Context)

        End Sub



CONTEXT Class : 


    Public Class MyContext
        Inherits ApplicationContext

        Private WithEvents mainFrm As Form

        Public Sub New(ByVal frm As Form)
            Me.SwitchTo(frm)
        End Sub

        Public Sub SwitchTo(ByVal frm As Form)

            Dim tmpFrm As Form = mainFrm
            mainFrm = frm
            If tmpFrm IsNot Nothing Then
                tmpFrm.Close()
                tmpFrm.Dispose()
                tmpFrm = Nothing
            End If
            If mainFrm IsNot Nothing Then
                mainFrm.Show()
            End If

        End Sub

        Private Sub mainFrm_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles mainFrm.Closed
            Application.ExitThread()
        End Sub

    End Class



HOW I LOAD THE USERCONTROL : 

    Public Shared Function Create(Of T)(ByVal aAssembly As String, ByVal aComponent As String) As T

            Dim mAsm As Assembly
            Dim mType As Type
            Dim mObj As Object
            Dim mT As T
            Dim mInterface As Type

            Try
                mAsm = Assembly.Load(aAssembly)
            Catch exArgumentNullExc As ArgumentNullException
                Return Nothing
            Catch exBadImageFormatExc As BadImageFormatException
                Return Nothing
            Catch exFileNotFoundExc As FileNotFoundException
                Return Nothing
            End Try

            mType = mAsm.GetType(New StringBuilder().Append(aAssembly).Append(".").Append(aComponent).ToString)

            If mType IsNot Nothing Then
                mInterface = mType.GetInterface("IDispatcher", False)
            Else
                Return Nothing
            End If

            If mInterface Is Nothing Then
                Return Nothing
            End If

            Try
                mObj = Activator.CreateInstance(mType)
            Catch exTargetInvocationException As TargetInvocationException
                Return Nothing
            End Try

            mT = CType(mObj, T)

            Return mT

        End Function




AND ONLY FOR WPF USERCONTROL :

Me._threadWPF.Start(New Object() {lLinkedItemList, m})
Me._waitEvent.WaitOne()

     Private Sub ThreadWPF(ByVal aObject As Object)

            Dim lArgs() As Object = DirectCast(aObject, Object())
            Dim lControl As System.Windows.Controls.Control
            Dim lLinkedItemList As List(Of LinkedItem) = DirectCast(lArgs(0), List(Of LinkedItem))
            Dim m As PBox = DirectCast(lArgs(1), PBox)

            'create the element host 
            lControl = Utils.Create(Of System.Windows.Controls.Control)(m.Widget.Assembly.Name, m.Widget.Name)

            If lControl IsNot Nothing Then

                Dim lElementHost As New ElementHost
                Dim lUserControl As New UserControl

                lElementHost.Dock = DockStyle.Fill

                lElementHost.Child = lControl

                lUserControl.Name = m.Widget.ID.ToString
                lUserControl.Controls.Add(lElementHost)

                lUserControl.Name = m.Widget.ID.ToString

                lLinkedItemList.Add(New LinkedItem(lUserControl.Name, lUserControl))

            End If

            Me._waitEvent.Set()

        End Sub

Open in new window

Avatar of Toony06
Toony06

You are trying to access a variable from a different thread. You need to check the access before accessing it with the lock keyword. Simply create an lock object before accessing the variable.


'Create a mutex and wait for an access
Dim lock As Mutex
lockMutex = New Mutex(False, "Mutex Name")
lockMutex.WaitOne()

'Do Your Work Here

'Release the lock for further access
lockMutex.ReleaseMutex()

Open in new window

Avatar of Dnx_7

ASKER

In fact, i did lot of tests and seems that is only when i affect the wpf usercontrol to the CHILD property of the elementhost...

then i tried to overrides this property but cannot do this at this time

don't know how to figure it out :(
ASKER CERTIFIED SOLUTION
Avatar of Toony06
Toony06

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Dnx_7

ASKER

It resolved my problemd