0

Suppose there is a Console Application, which prints text into command window. Also there is the Logger WPF window, which has to duplicate output. IDE forces me to create window inside new thread (STA):

public SomeClass()
{
    var loggerThread = new Thread(() =>
    {
        var logWindow = new Window
        {
            Title = "Logger", Width = 100, Height = 100
        };

        var stackPanel = new StackPanel 
        {
            Name = "stackPanel"
        };

        stackPanel.Children.Add(new TextBlock 
        {
            Name = "textBlock", Text = "new text\n"
        });

        logWindow.Content = stackPanel;
        logWindow.ShowDialog();
    });

    loggerThread.SetApartmentState(ApartmentState.STA);
    loggerThread.IsBackground = true;
    loggerThread.Start();
}

public void PutInfo(string msg)
{
    // how to access textBlock here?
    ...textBlock.Text = "some info";
}

How can I access textBlock.Text after the thread is started. In other words, how to access UI elements in that thread from another classes through PutInfo() method?

andreikashin
  • 1,528
  • 3
  • 14
  • 21
  • 1
    Search for SynchronizationContext. BTW I think this is a duplicate of e.g. http://stackoverflow.com/questions/11625208/accessing-ui-main-thread-safely-in-wpf – Andre Jul 05 '16 at 13:33

1 Answers1

2

You have crossed a couple of lines here, A Console app is an app with no Graphical elements

A WPF App is an app that has a Graphical User interface with WPF defining the interface.

so by Definition a console app can't have a GUI

now if you are trying to record the output of a console app in a GUI then you can user the Process Class in System.Diagnostics to capture and display the console output channels which is nicely explained here Capturing console output from a .NET application (C#)

if you want the console app to have direct control of a different GUI apps controls then you are breaching memory management and should look into using unmanaged memory pointers though i would not recommend this

if you're just trying to update a WPF textblock then that is simple, just set your logger class to be observable either by storing the text in an observable collection or a string property that implements INotifyPropertyChanged and then use binding to update eg

public class Logger:INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged
    private string _Description;
    public static readonly PropertyChangedEventArgs DescriptionProperty = new PropertyChangedEventArgs(nameof(Description));

    public string Description
    {
        get { return _Description; }
        set
        {
            _Description = value;
            PropertyChanged?.Involke(this, DescriptionProperty);
        }
    }
}

then this is all this is needed to update the control

<TextBox Text="{Binding Description, source="Your Logger"}"/>

then every time you change Description using the setter the textblock updates automatically

Community
  • 1
  • 1
MikeT
  • 5,398
  • 3
  • 27
  • 43
  • It creates a window in a new thread. The problem is to access window's UI elements from other classes in order to update text field. – andreikashin Jul 05 '16 at 14:01
  • if all you want is to update the text then your are massively over complicating it and have poorly worded the question. updated answer to show how to bind WPF – MikeT Jul 05 '16 at 14:31