线程忙时WPF重绘窗口

时间:2014-09-26 08:31:25

标签: c# wpf

以下是我的问题的简短示例。 在函数的开头我想改变一些视觉参数,例如 隐藏窗口,让它变红("我的例子"),在功能结束时,我想把它放回去。 Somethig喜欢鼠标等待光标以获得长期功能。

在功能OnButtonClick结束之前,是否有任何优雅的方法使按钮变为红色 - 允许窗口消息循环以并行方式处理请求 Background = Red 并立即重绘窗口的方法。

private void OnButtonClick(object sender, RoutedEventArgs e)
{            
            System.Windows.Media.Brush br = ((Button)sender).Background;
            ((Button)sender).Background = System.Windows.Media.Brushes.Red;

            Mouse.OverrideCursor = Cursors.Wait;
            Function(); //long-term function 
            Mouse.OverrideCursor = Cursors.Arrow;

            ((Button)sender).Background = br;                  
}

2 个答案:

答案 0 :(得分:1)

您可以在新线程中运行它,后台工作者或使用任务并行库(见下文)。

private void OnButtonClick(object sender, RoutedEventArgs e)
{            
            System.Windows.Media.Brush br = ((Button)sender).Background;
            ((Button)sender).Background = System.Windows.Media.Brushes.Red;

            Mouse.OverrideCursor = Cursors.Wait;

            // Run function in a new thread.
            Task.Factory.StartNew(() =>
            {
                Function(); // Long running function.
            })
            .ContinueWith((result) =>
                {
                    // Runs when Function is complete...
                    Mouse.OverrideCursor = Cursors.Arrow;
                    ((Button)sender).Background = br;       
                }); 


}

如果您使用的是.NET 4.5,也可以使用Async / Await关键字执行此操作。

答案 1 :(得分:0)

有一种简单的方法可以做到这一点 xaml:

<Button Command="{Binding TestCommand}" Content="Test" Focusable="False" Background="Green">
    <Button.Resources>
        <Style TargetType="Button">
            <Style.Triggers>
               <DataTrigger Binding="{Binding Loading}" Value="true">
                   <Setter Property="Background" Value="Red"/>
               </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Resources>
</Button>  

这样,如果Loading = false

,它会将按钮背景设置为绿色

的.cs:

public class VM : INotifyPropertyChanged
{
    public bool Loading
    {
        get { return _loading; }
        private set
        {
            if (value.Equals(_loading)) return;
            _loading = value;
            OnPropertyChanged("Loading");
        }
    }
    public RelayCommand TestCommand
    {
        get { return _testCommand; }
    }

    void Test(object parameter)
    {
        Dispatcher.CurrentDispatcher.BeginInvoke( (Action) (() => Loading = true));
        //or if you want to do it with more responsive UI then use
        Dispatcher.CurrentDispatcher.Invoke( (Action) (() => Loading = true));
        doSomething(); //this could be replaced with BackgroundWorker DoWork function  
        //or this code could be the DoWork function.
        Loading = false;
    }
}