Проблемы с обновлением WPF при привязке к console.stdout - PullRequest
1 голос
/ 19 декабря 2008

Я создаю небольшое приложение wpf на C #. Когда на кнопку нажимают третью Функция party dll создает древовидный объект. Этот объект связан к дереву. Это работает нормально, но занимает немного времени для загрузки. Как Функция dll создает объект, который выводит информацию о прогрессе в приставка. Я хочу перенаправить это в TextBlock, чтобы пользователь получает видеть сообщения о прогрессе.

Мой окно ctor выглядит так:

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

xaml:

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

Класс StringRedir показан ниже. Проблема в TextBlock для по какой-то причине не обновляется с сообщениями, пока TreeView загружается. Пошагово я вижу, что свойство Text обновляется но TextBlock не обновляется. Я добавил MessageBox.Show () в точке, где текст обновляется, и это, кажется, вызывает окно, чтобы обновить каждый раз, и я могу видеть каждое сообщение. Так что я думаю, мне нужен какой-то способ явно обновить экран ... но это не имеет смысла, я думал, что привязка данных приведет к визуальному обновить, когда свойство изменилось. Что мне здесь не хватает? Как я заставить его обновить? Любой совет приветствуется!

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"); 
    } 


} 

Ответы [ 3 ]

1 голос
/ 19 декабря 2008

Вы не включили код, который загружает данные для TreeView, но я предполагаю, что это делается в потоке пользовательского интерфейса. Если это так, это будет блокировать любые обновления пользовательского интерфейса (включая изменения TextBlock) до тех пор, пока оно не будет завершено.

1 голос
/ 20 декабря 2008

Итак, после прочтения модели потоков WPF (http://msdn.microsoft.com/en-us/library/ms741870.aspx) я, наконец, получил ее обновить, вызвав Dispatcher Invoke () с приоритетом Dispatch, установленным в Render. Как предположил Кент выше, обновления пользовательского интерфейса в очереди диспетчера, вероятно, имели низкий приоритет. Я закончил тем, что делал что-то вроде этого.

XAML

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

C # target обновленный код обработчика

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);
}

Примечание. Раньше я использовал TextBlock, но я переключился на TextBox, поскольку он поставляется с прокруткой

Я все еще чувствую себя неловко из-за всего потока. Есть лучший способ сделать это? Спасибо Мэтту и Кенту за их комментарии. Если бы у меня были очки, пометили бы их ответы как полезные.

0 голосов
/ 19 декабря 2008

Я считаю, что проблема в конструкторе вашего класса StringRedir. Вы передаете ProgessTextBlock и делаете это с ним:

local.Text = "";

Это фактически перезаписывает ранее установленное значение для ProgressTextBlock.Text, которое было таким:

{Binding Text}

Видишь, о чем я? Явно установив значение для свойства Text TextBlock, вы отменили привязку.

Если я читаю правильно, похоже, что идея передать TextBlock в ctor StringRedir - это похмелье до того, как вы попытались связать напрямую. Я бросил бы это и придерживался идеи связывания, поскольку это больше в духе WPF.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...