WPF issues with updating textblock related to consolestdout

I am creating a small wpf application in C #. When the button is clicked, the third hand dll function creates a tree type object. This object is linked to a tree structure. This works great, but it takes a little time to load. Since the dll creates an object it prints progress information to the console. I want to redirect this to a TextBlock so that the user receives progress messages.

My ctor window looks like this:

InitializeComponent (); 
StringRedir s = new StringRedir (ref ProgressTextBlock); 
Console.SetOut (s); 
Console.SetError (s); 
this.DataContext = s; 

xaml:

<
      

TextBlock Text = "{Binding Path = Text}" Width = "244" x: Name = "ProgressTextBlock" TextWrapping = "Wrap" /> <

TreeView> ... <

/ TreeView>

The StringRedir class is shown below. The problem is that the TextBlock for some reason is not updated with messages until the TreeView is loaded. Proceeding I can see that the Text property is updating but the TextBlock is not updating. I added a MessageBox.Show () at the point where the text is updated and this seems to cause it to update every time and I can see every message. So I think I need to explicitly refresh the screen somehow ... but that doesn't make sense, I thought that data binding would cause a visual refresh when the property changed. What am I missing here? How do I get it for an update? Any advice is appreciated!

public class StringRedir : StringWriter , INotifyPropertyChanged 
{ 
    private string text; 
    private TextBlock local; 


    public string Text { 
        get{ return text;} 
        set{ 
            text = text + value; 
            OnPropertyChanged("Text"); 
        } 
    } 


    public event PropertyChangedEventHandler PropertyChanged; 
    protected void OnPropertyChanged(string name) 
    { 
        PropertyChangedEventHandler handler = PropertyChanged; 
        if (handler != null) 
        { 
            handler(this, new PropertyChangedEventArgs(name)); 
        } 
    } 


    public StringRedir(ref TextBlock t) 
    { 
        local = t; 
        Text = ""; 
    } 


    public override void WriteLine(string x) 
    { 
        Text = x +"\n"; 
        //MessageBox.Show("hello"); 
    } 


} 

      

+1


source to share


3 answers


You haven't included the code that loads the data for TreeView

, but I'm assuming it's done on the UI thread. If so, this will block any UI updates (including changes to TextBlock

) until it completes.



+1


source


So after some reading in WPF threading model ( http://msdn.microsoft.com/en-us/library/ms741870.aspx ) I finally got it to update by calling Dispatcher Invoke () with dispatch priority set for Render. As Kent suggested, updating the UI in the dispatcher queue was likely a low priority. I ended up doing something like this.

XAML

<TextBox VerticalScrollBarVisibility="Auto"  
         Text="{Binding Path=Text, NotifyOnTargetUpdated=True}"
         x:Name="test" TextWrapping="Wrap" AcceptsReturn="True" 
         TargetUpdated="test_TargetUpdated"/>

      

Updated C # handler code



private void test_TargetUpdated (object sender, DataTransferEventArgs e)
{
    TextBox t = sender as TextBox;
    t.ScrollToEnd ();
    t.Dispatcher.Invoke (new EmptyDelegate (() => {}), System.Windows.Threading.DispatcherPriority.Render);
}

Note. I used to use TextBlock, but I changed it to TextBox as it has scrolling

However, I still feel uneasy about the whole stream. Is there a better way to do this? Thanks to Matt and Kent for their comments. If I had points, they would mark their answers as helpful.

+1


source


I believe the problem is with the constructor of your StringRedir class. You pass into the ProgessTextBlock and you do this with it:

local.Text = "";

      

This actually overwrites the previously set value for ProgressTextBlock.Text, which was the following:

{Binding Text}

      

See what I mean? By explicitly setting a value for the TextBlock Text property, you unbind.

If I'm reading correctly, it looks like the idea of ​​passing a TextBlock to a StringRedir ctor is a hangover before you try to bind it directly. I would rip it up and stick with the idea of ​​binding as it is more in the "spirit" of WPF.

0


source







All Articles