简体   繁体   中英

WPF Update grid visibility

After some search on web I have set up this simple example:

PropertyChangedBase.cs

public class PropertyChangedBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName) {
        //Raise the PropertyChanged event on the UI Thread, with the relevant propertyName parameter:
        Application.Current.Dispatcher.BeginInvoke((Action)(() => {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }));
    }
 }

UserViewModel.cs

public class UserViewModel : PropertyChangedBase
{
    private Visibility _showUserWindow = Visibility.Collapsed;
    public Visibility ShowUserWindow {
        get { return _showUserWindow; }
        set {
            _showUserWindow = value;
            OnPropertyChanged("ShowUserWindow"); //This is important!!!
        }
    }
}

MainWindow.xaml

<Window x:Class="WpfApplication1.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>
        <Grid Margin="43,28,247,129" Background="AliceBlue" Visibility="{Binding ShowUserWindow}"/>
        <Button Content="Button" HorizontalAlignment="Left" Margin="349,150,0,0" VerticalAlignment="Top" Width="75" PreviewMouseLeftButtonDown="Button_PreviewMouseLeftButtonDown"/>
    </Grid>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    UserViewModel userViewModel;

    public MainWindow() {
        InitializeComponent();

        userViewModel = new UserViewModel();
        DataContext = userViewModel;
    }

    private void Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
        userViewModel.ShowUserWindow = Visibility.Visible;
        Thread.Sleep(1000);
        userViewModel.ShowUserWindow = Visibility.Collapsed;
    }
}

Right now grid becomes collapsed after 1 sec, I would like to update UI before timer starts. What I am doing wrong?

Edit: Thread.Sleep line immitates some work, that takes some time to complete. Grid should become visible before work starts and show some info about that work and become collapsed after work is done.

Well, you should consider doing the Thread.Sleep(1000) operation on a separate thread, not on the UI thread. Check this for that. Other than that, try to use yourGrid.UpdateLayout() method after setting its visibility to collapsed .

LE: Most probably, his Thread.Sleep(1000) stands for something like a database operation, for example, something that takes time.

LE2: A BackgroundWorker will do the trick. Check this link !

If you are using .NET 4.5, you can use Task.Delay() to allow UI to update itself before starting the actual work:

private async void Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
    userViewModel.ShowUserWindow = Visibility.Visible;
    await Task.Delay(1);
    Thread.Sleep(1000);
    userViewModel.ShowUserWindow = Visibility.Collapsed;
}

Please note that await Task.Delay(1); should be used even after you replace Thread.Sleep(1000) with actual work.

However this should be used only if your work can be done only in UI thread and cannot be moved to a background thread (for example, massive loading of UI elements). Otherwise the correct approach is to move the work to a background thread:

private async void Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
    userViewModel.ShowUserWindow = Visibility.Visible;
    await Task.Start(() => {
        Thread.Sleep(1000);
    };
    userViewModel.ShowUserWindow = Visibility.Collapsed;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM