John Starling
John Starling

Reputation: 23

Make WPF-control shared

I'm trying to access Label from another class's method running in background thread with the help of MainWindow Class's Public Shared Sub like this:

    Private Delegate Sub ProgressReportInvoker(ByVal progressStr As String)

    Public Shared Sub ProgressReport(ByVal progressStr As String)
        If MainWindow.Label.Dispatcher.CheckAccess() Then
            MainWindow.Label.Content = progressStr
        Else
            MainWindow.Label.Dispatcher.Invoke(
                            New ProgressReportInvoker(AddressOf ProgressReport),
                            progressStr)
        End If
    End Sub

Call from another class is below:

MainWindow.ProgressReport("Sample text") 

But I have this error on "MainWindow.Label":

Reference to a non-shared member requires an object reference.

I noticed that if I declare Label in MainWindow.g.i.vb as Public Shared than error is gone:

#ExternalSource ("..\..\MainWindow.xaml", 11)
    <System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")>
    Public Shared WithEvents Label As System.Windows.Controls.Label

#End ExternalSource

But this file is generated automatically from the *.XAML file so it takes previous look when I compile the code.

Is there any way to make control shared in *.XAML file or may be there are any alternatives of making my task possible?

Upvotes: 2

Views: 352

Answers (2)

mm8
mm8

Reputation: 169160

You should access the instance of the MainWindow and not the type itself:

Public Shared Sub ProgressReport(ByVal progressStr As String)
    Dim mainWindow = Application.Current.Windows.OfType(Of MainWindow).FirstOrDefault()
    If mainWindow.Label.Dispatcher.CheckAccess() Then
        mainWindow.Label.Content = progressStr
    Else
        mainWindow.Label.Dispatcher.Invoke(
                            New ProgressReportInvoker(AddressOf ProgressReport),
                            progressStr)
    End If
End Sub

I tried this before but problem is in multitasking. I can't access the form from another thread without some special moves which I don't know about

You can only access a UI control in the thread on which it was originally created:

Application.Current.Dispatcher.BeginInvoke(New Action(Sub()
                                                          Dim mainWindow = Application.Current.Windows.OfType(Of MainWindow).FirstOrDefault()
                                                          mainWindow.Label.Content = progressStr
                                                      End Sub))

Upvotes: 1

Ondřej
Ondřej

Reputation: 1673

It is very bad practice to use anything global (shared/static). Use instance of class or other mechanism (Dependency Injection, messaging, events, etc.) for communication between independent classes.

Upvotes: 0

Related Questions