2012-05-23 2 views
0

У меня есть <Border>, внутри которого есть <Image> и <Textblock>, и я пытаюсь изменить текст текстового блока на Mouseleftbutton down, так как в этом событии click есть более длинная операция, текст текста блок не изменяется до завершения этой операции.Измените текст в текстовом блоке на клике

также я пробовал Dispatcher.BeginInvoke(), но не удался.

Вот мой код:

<Border x:Name="btnReadMe" Grid.Row="0" Style="{StaticResource BorderStyle1}" MouseLeftButtonDown="btnReadMe_MouseLeftButtonDown" MouseLeftButtonUp="btnReadMe_MouseLeftButtonUp" > 
    <Border.Background> 
     <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"> 
      <GradientStop Color="#46c746" Offset="0"/> 
      <GradientStop Color="#129312" Offset="1"/> 
     </LinearGradientBrush> 
    </Border.Background> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="3*"/> 
      <ColumnDefinition Width="6*"/> 
     </Grid.ColumnDefinitions> 
     <Image Grid.Column="0" Source="/CareFamily.AtHome;component/Resources/read_message-read_it.png" Margin="5,15" > 
      <Image.RenderTransform> 
       <ScaleTransform ScaleX="1" ScaleY="1"/> 
      </Image.RenderTransform> 
     </Image> 
     <StackPanel Grid.Column="1" Margin="0,10,0,10" VerticalAlignment="Center"> 
      <TextBlock Name="tbReadToMe" Text="Read to Me" Style="{StaticResource TextBlockStyle1}" Margin="0,0,0,0" /> 
     </StackPanel> 
    </Grid> 
</Border> 

SpVoice voice; 
private void btnReadMe_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
{ 
    if (voice == null) 
     voice = new SpVoice(); 


    string readMessageState = tbReadToMe.Text; 
    switch (readMessageState) 
    { 
     case "Read to Me": 
      { 
       tbReadToMe.Text = "Pause"; 
       break; 
      } 

     case "Pause": 
      { 
       tbReadToMe.Text = "Resume"; 
       voice.Pause(); 
       break; 
      } 

     case "Resume": 
      { 
       tbReadToMe.Text = "Pause"; 
       voice.Resume(); 
       break; 
      } 
     default: 
      { 
       tbReadToMe.Text = "Read to Me"; 
       break; 
      } 
    } 


    if (!string.IsNullOrEmpty(Msg.Subject)) 
    { 
     voice.Speak(Msg.Subject, SpeechVoiceSpeakFlags.SVSFDefault); 
    } 
    if (!string.IsNullOrEmpty(Msg.Body)) 
    { 
     voice.Speak(Msg.Body, SpeechVoiceSpeakFlags.SVSFDefault); // Length operation 
    } 
} 
+0

Вы призывающую к длительной операции на отдельном потоке? Если нет, он запускается в потоке пользовательского интерфейса, и вызов изменения текста в Диспетчере ничего не сделает, поскольку он ждет завершения длительной операции. Увидеть часть вторичной операции поможет. Кроме того, вы можете захотеть изучить класс «BackgroundWorker» и его событие «ProgressChanged». –

ответ

0

Выполнить вашу длинную операцию на тему и использовать

Dispatcher

в

для обновления пользовательского интерфейса соответственно.

Пример кода:

var opThread = new Thread(delegate() 
{ 
    //your lengthy operation 

    tbReadToMe.Dispatcher.Invoke(new Action(delegate 
    { 
     tbReadToMe.Text = "Pause"; 
    })); 

    //your lengthy operation 

    tbReadToMe.Dispatcher.Invoke(new Action(delegate 
    { 
     tbReadToMe.Text = "etc..."; 
    })); 
}); 

opThread.Start(); 
+0

нет нет успеха ... такой же я выложил длинную часть операции в Dispatcher.BeginInvoke ... – BreakHead

+0

давайте посмотрим ваш код и посмотрим мое обновление ... – animaonline

-1

Используйте Application.DoEvents() перед вашей "долгой" операции!

+0

нет приложения Applicion.DoEvents() в моем приложении WPF ... – BreakHead

+0

, что просто неправильно, System.Windows.Forms.Application.DoEvents() не следует использовать для этого. Длительная операция не должна выполняться на основном потоке. Это, вероятно, будет работать, но этого следует избегать. – animaonline

+0

Это выбор кодера! Я не был уверен, что в wpf есть 'Application.DoEvents()'. Так жаль! И мой ответ будет использовать ['BackgroundWorker'] (http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx) для использования для вашей работы. Это лучше, чем использование MultiThreading! – Writwick

0

Причина Dispatcher.BeginInvoke() не помогла, потому что, несмотря на то, что она работает как асинхронно, она все еще делает это в потоке основного/пользовательского интерфейса. Сделайте свою длительную операцию в фоновом потоке, используя класс BackgroundWorkerThread.

Я работал на небольшой образец, чтобы продемонстрировать:

Window1.xaml:

<Window x:Class="BackgroundWorkerExample.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Window1" Height="300" Width="663"> 
<Grid> 
    <TextBox PreviewMouseDown="textBox1_PreviewMouseDown" Height="38" Margin="24,34,26,0" Name="textBox1" VerticalAlignment="Top" FontSize="24"> 
     The quick Velociraptor jumped over the torpid tapir. 
    </TextBox> 
</Grid> 

Window1.xaml.cs:

using System.Windows; 
using System.Windows.Input; 
using System.ComponentModel; 
using System.Threading; 
using System.Windows.Media; 
using System; 

namespace BackgroundWorkerExample 
{ 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
     } 


     void _asyncSpeakerThread_DoWork(object sender, DoWorkEventArgs e) 
     { 
      // Change color of text to Red to indicate Start of operation 
      this.Dispatcher.BeginInvoke(new Action(() => { textBox1.Foreground = Brushes.Red; })); 

      string text = e.Argument as string; 
      //voice.Speak(text, SpeechVoiceSpeakFlags.SVSFDefault); // Lengthy operation 
      Thread.Sleep(1000); // Simulate lengthy operation 

      // Change color of text to Black to indicate End of operation 
      this.Dispatcher.BeginInvoke(new Action(() => { textBox1.Foreground = Brushes.Black; })); 
     } 

     private void textBox1_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
     { 
      BackgroundWorker bw = new BackgroundWorker(); 

      bw.DoWork += new DoWorkEventHandler(_asyncSpeakerThread_DoWork); 
      string workerArgument = textBox1.Text; 
      bw.RunWorkerAsync(workerArgument); 
     } 
    } 
}