WPF中LABEL文本不及时更新的问题,求指导

ja12 2014-02-09 04:48:54
在学习WPF的时候发现Label的Content在程序运行中改变时不在窗体上立即更新,而总是只显示最后一次赋值结果。用了几种方法都是这样,求大神指导。以下为我的代码。
第一种:
前台:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="249*" />
<ColumnDefinition Width="254*" />
</Grid.ColumnDefinitions>
<Label Name="state" Margin="0,0,0,247" Grid.ColumnSpan="2" Content="{Binding Path=Textstring,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Background="Brown"/>
<Button Grid.ColumnSpan="2" Height="43" VerticalAlignment="Bottom" Margin="142,0,150,168" Name="Button1">运行</Button>
</Grid>
</Window>
后台:
Imports System.Threading
Imports System.ComponentModel
Imports System.Windows.Threading

Class MainWindow
Partial Class TextState
Implements INotifyPropertyChanged
Private _Textstring As String
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public Property Textstring As String
Get
Return _Textstring
End Get
Set(ByVal value As String)
_Textstring = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Textstring"))
End Set
End Property
End Class
Public mystring As String

Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
mystring = "正在进行计算,请稍后"
Dim TextState1 As New TextState
state.DataContext = TextState1
TextState1.Textstring = mystring
For i = 0 To 2
TextState1.Textstring = i
Next
End Sub
End Class
第二种:
前台
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="249*" />
<ColumnDefinition Width="254*" />
</Grid.ColumnDefinitions>
<Label Name="state" Margin="0,0,0,248" Grid.ColumnSpan="2" Background="Brown"/>
<Button Grid.ColumnSpan="2" Height="37" VerticalAlignment="Bottom" Margin="165,0,179,170" Name="Button1">运行</Button>
</Grid>
</Window>
后台:
Imports System.Threading
Imports System.ComponentModel
Imports System.Windows.Threading
Class MainWindow
Public mystring As String
Private Delegate Sub MyDelegate(mystring As String)
Private Sub ThreadMethod()
If state.Dispatcher.CheckAccess() Then
Settext(mystring)
Else
Dim myDelegate As MyDelegate = New MyDelegate(AddressOf Settext)
state.Dispatcher.BeginInvoke(DispatcherPriority.Send, myDelegate, mystring)
End If
End Sub
Private Sub Settext(mystring As String)
state.Content = mystring
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
Dim myThread As Thread = New Thread(AddressOf ThreadMethod)
myThread.IsBackground = True
mystring = "正在进行计算,请稍后"
myThread.Start()
For i = 0 To 2
mystring = i
Next
End Sub
End Class
...全文
738 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
vbfool 2014-03-31
  • 打赏
  • 举报
回复
引用 10 楼 xtayhame 的回复:
[quote=引用 9 楼 vbfool 的回复:] 经测试通过,UI线程和其它线程的交互,可能真是个难点,不知道我这个例子能不能让你看懂。 另一个,UI线程的刷新其实是周期性的,你在数据线程中没有足够的延时的话,UI线程刷新上去的,只会是最后一个值。
那如果我要用textbox显示程序进行进度的信息要跟这样写?有更简捷的方法吗?
    Private Sub Button_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
       Dim t As New TestClass
        Me.DataContext = t
        Dim th As New System.Threading.Thread(Sub()
                                                  计算程序1()
                                                  Me.Dispatcher.BeginInvoke(New Action(Sub() t.Text = "进度消息1"))
                                                  System.Threading.Thread.Sleep(1000)
                                                  计算程序2()
                                                  Me.Dispatcher.BeginInvoke(New Action(Sub() t.Text = "进度消息2"))
                                                  System.Threading.Thread.Sleep(1000)
                                              End Sub)
        th.Start()
    End Sub
[/quote] 差不多也就这样了,你看看实际上已经没几行代码了。
ja12 2014-03-29
  • 打赏
  • 举报
回复
引用 9 楼 vbfool 的回复:
经测试通过,UI线程和其它线程的交互,可能真是个难点,不知道我这个例子能不能让你看懂。 另一个,UI线程的刷新其实是周期性的,你在数据线程中没有足够的延时的话,UI线程刷新上去的,只会是最后一个值。
那如果我要用textbox显示程序进行进度的信息要跟这样写?有更简捷的方法吗?
    Private Sub Button_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
       Dim t As New TestClass
        Me.DataContext = t
        Dim th As New System.Threading.Thread(Sub()
                                                  计算程序1()
                                                  Me.Dispatcher.BeginInvoke(New Action(Sub() t.Text = "进度消息1"))
                                                  System.Threading.Thread.Sleep(1000)
                                                  计算程序2()
                                                  Me.Dispatcher.BeginInvoke(New Action(Sub() t.Text = "进度消息2"))
                                                  System.Threading.Thread.Sleep(1000)
                                              End Sub)
        th.Start()
    End Sub
vbfool 2014-03-15
  • 打赏
  • 举报
回复
引用 8 楼 xtayhame 的回复:
[quote=引用 6 楼 vbfool 的回复:] [quote=引用 5 楼 xtayhame 的回复:] 多谢sp1234的指导,可是我这两个程序按你说的改了后仍然是主线程运行结束后才刷新啊,显示也是最后一次赋值。
我觉得你根本没搞懂是怎么回事,还有,你的循环那么快,能看出效果才有鬼。[/quote] 我如果搞懂了还会来问吗,费话,还有,我这个程序中的循环只是把大量的计算替代成了数字变化,只是为了在这里方便人好看,不是真的要他显示数字。而且问题也不是在这里,别说sleep(1500)了,sleep(15000)的效果也是一样的,这些都是我试过了不行才来问。[/quote]

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
            <TextBlock Text="{Binding Text}"  Width="75" Height="32" Margin="10"/>
            <Button Content="测试" Click="Button_Click" Width="75" Height="32" Margin="10"/>
        </StackPanel>
    </Grid>
</Window>

Class MainWindow

    Private Sub Button_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
        Dim t As New TestClass
        Me.DataContext = t
        Dim th As New System.Threading.Thread(Sub()
                                                  For index = 1 To 10
                                                      Dim i = index

                                                      Me.Dispatcher.BeginInvoke(New Action(Sub() t.Text = i.ToString()))
                                                      System.Threading.Thread.Sleep(1000)
                                                  Next

                                              End Sub)
        th.Start()
    End Sub
End Class
Public Class TestClass
    Implements System.ComponentModel.INotifyPropertyChanged

    Private m_Text As String
    Public Property Text() As String
        Get
            Return m_Text
        End Get
        Set(ByVal value As String)
            m_Text = value
            RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs("Text"))

        End Set
    End Property


    Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class

经测试通过,UI线程和其它线程的交互,可能真是个难点,不知道我这个例子能不能让你看懂。 另一个,UI线程的刷新其实是周期性的,你在数据线程中没有足够的延时的话,UI线程刷新上去的,只会是最后一个值。
ja12 2014-03-14
  • 打赏
  • 举报
回复
引用 6 楼 vbfool 的回复:
[quote=引用 5 楼 xtayhame 的回复:] 多谢sp1234的指导,可是我这两个程序按你说的改了后仍然是主线程运行结束后才刷新啊,显示也是最后一次赋值。
我觉得你根本没搞懂是怎么回事,还有,你的循环那么快,能看出效果才有鬼。[/quote] 我如果搞懂了还会来问吗,费话,还有,我这个程序中的循环只是把大量的计算替代成了数字变化,只是为了在这里方便人好看,不是真的要他显示数字。而且问题也不是在这里,别说sleep(1500)了,sleep(15000)的效果也是一样的,这些都是我试过了不行才来问。
qdu123 2014-03-05
  • 打赏
  • 举报
回复
引用 3 楼 sp1234 的回复:
对于第二个程序也是一样,而且你用了子线程,比第一个错的更加离谱。你的主线程仍然是设置完毕 mystring=2 之后,才能去响应ThreadMethod里边的动作的。 合适的做法是:把你的for循环语句放到ThreadMethod里边去执行,而不是放到UI主线程执行。
老兄说的在理,其实lz可以通过多线程使用委托来实现更新ui,还有你循环太快了,你眼睛反应不过来,在循环赋值后加sleep(1500)看看,具体怎么写百度
vbfool 2014-03-04
  • 打赏
  • 举报
回复
引用 5 楼 xtayhame 的回复:
多谢sp1234的指导,可是我这两个程序按你说的改了后仍然是主线程运行结束后才刷新啊,显示也是最后一次赋值。
我觉得你根本没搞懂是怎么回事,还有,你的循环那么快,能看出效果才有鬼。
ja12 2014-02-10
  • 打赏
  • 举报
回复
多谢sp1234的指导,可是我这两个程序按你说的改了后仍然是主线程运行结束后才刷新啊,显示也是最后一次赋值。
  • 打赏
  • 举报
回复
引用 1 楼 Ptrtoptr 的回复:
兄弟,我很想帮你可,我用的是C#, 不懂VB啊
vb.net 和 c# 基本上一样。一个好的c#程序员,应该可以稍加注意就能看懂vb.net的每一行代码。
  • 打赏
  • 举报
回复
对于第二个程序也是一样,而且你用了子线程,比第一个错的更加离谱。你的主线程仍然是设置完毕 mystring=2 之后,才能去响应ThreadMethod里边的动作的。 合适的做法是:把你的for循环语句放到ThreadMethod里边去执行,而不是放到UI主线程执行。
  • 打赏
  • 举报
回复
你啥时候见过一个阻塞着的UI线程会刷新UI?只有当你的程序(暂时)结束处理之后,UI线程才会刷新界面。 当然你可以强制刷新一下,例如调用 grid.UpdateLayout 语句。但是最好释放到真正符合设计模式的“定时器”中去搞什么“数字跳动”游戏。
Ptrtoptr 2014-02-09
  • 打赏
  • 举报
回复
兄弟,我很想帮你可,我用的是C#, 不懂VB啊

16,554

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧