Search code examples
vb.netmvvmbindingthread-sleep

Mvvm. Textbox never change with System.Threading.Thread.Sleep


I want change a textbox value, but this code doesn't work. I see only the last value. If you want to help me copy and paste the code . Thanks a lot

This is XAML

    <TextBox HorizontalAlignment="Left" Height="46" 
           Margin="4,4,4,4" VerticalAlignment="Top" Width="162" 
           Text="{Binding Path=Msg,  
           Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

This is VB code.

Imports System.Threading
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System

Class MainWindow

   Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
       Dim x As New Abc
       Me.DataContext = x
   End Sub
End Class

Public Class Abc
Implements INotifyPropertyChanged

Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

Private Sub OnPropertyChanged(ByVal info As String)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub

Protected Sub OnNotifyPropertyChanged(propertyName As String)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub

Private Property _Msg As String
Public Property Msg As String
    Get
        Return _Msg
    End Get
    Set(value As String)
        _Msg = value
        OnPropertyChanged("Msg")
    End Set
End Property

Private m_ButtonCommand As ICommand
Public Property ButtonCommand() As ICommand
    Get
        Return m_ButtonCommand
    End Get
    Set(value As ICommand)
        m_ButtonCommand = value
    End Set
End Property


Public Sub displayMessage(ByVal param As Object)
    Msg = "How"
    System.Threading.Thread.Sleep(1000)

    Msg = "Are"
    System.Threading.Thread.Sleep(1000)

    Msg = "you"
    System.Threading.Thread.Sleep(1000)

    Msg = "?"
    System.Threading.Thread.Sleep(1000)
End Sub

Private Function CandisplayMessage(ByVal param As Object) As Boolean
    Return True
End Function

Public Sub New()
    m_ButtonCommand = New DelegateCommand(AddressOf displayMessage, AddressOf CandisplayMessage)
End Sub
End Class


Public Class DelegateCommand
Implements ICommand

Private m_canExecute As Func(Of Object, Boolean)
Private m_executeAction As Action(Of Object)
Private m_canExecuteCache As Boolean

Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) Implements ICommand.CanExecuteChanged

Public Sub New(ByVal executeAction As Action(Of Object), ByVal canExecute As Func(Of Object, Boolean))
    Me.m_executeAction = executeAction
    Me.m_canExecute = canExecute
End Sub

Public Function CanExecute(ByVal parameter As Object) As Boolean Implements ICommand.CanExecute
    Dim temp As Boolean = m_canExecute(parameter)
    If m_canExecuteCache <> temp Then
        m_canExecuteCache = temp
        RaiseEvent CanExecuteChanged(Me, New EventArgs())
    End If
    Return m_canExecuteCache
End Function

Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
    m_executeAction(parameter)
End Sub
End Class

.............................................


Solution

  • When you use Thread.Sleep on UI Thread you block the UI thread, So nothing can happen in UI. If you want to show a 1 second wait after each message you have two choices.

    1 - Using the Delay command in an Async method. https://msdn.microsoft.com/en-us/library/hh194873(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-4

    2 - Using a dispatcher frame, which can let the dispatcher work while your method waits. http://www.codeproject.com/Articles/152137/DispatcherFrame-Look-in-Depth

    Unfortunately I'm not a VB programmer, But the code in c# would be like this.

    Async Sample:

    public Task displayMessage(object param){
        Msg = "How";
        await Task.Delay(1000); 
    
        Msg = "Are";
        await Task.Delay(1000);
    
        Msg = "you";
        await Task.Delay(1000);
    
        Msg = "?";
        await Task.Delay(1000);
    }
    

    DispatcherFrame sample:

    public void displayMessage(object param){
        Msg = "How";
        Wait(1000);
    
        Msg = "Are";
        Wait(1000);
    
        Msg = "you";
        Wait(1000);
    
        Msg = "?";
        Wait(1000);
    }
    
    
    public void Wait(int sleep)
    {
        var dFrame = new DispatcherFrame();
    
        ThreadPool.QueueUserWorkItem(state => {
            Thread.Sleep(sleep);
            dFrame.Continue = false;
        });
    
        Dispatcher.PushFrame(dFrame);
    }