长时间操作前请禁用WPF中的按钮

时间:2019-06-06 09:17:37

标签: c# wpf multithreading user-interface

在延迟(代码中的{Thread.Sleep()试图模仿I / O操作)之后,我想从另一个线程更改WPF窗口的背景。按下按钮时将调用该动作。

更具体地说,当我单击该按钮时,

  1. 禁用按钮
  2. 背景颜色改变后     延迟秒数
  3. 要再次启用的按钮

当我运行应用程序并触发事件时,我看不到禁用的按钮。尽管确实发生了背景变化,但我猜想它与UI线程和Dispatcher有关。但是我也尝试过这样禁用它

MyButton.Dispatcher.Invoke(() => MyButton.IsEnabled = false)

没有成功。

有人能解释为什么会发生这种情况吗,我该如何解决呢?

XAML

<Window x:Class="ThreadingModel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ThreadingModel"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="450"
        Width="800">
  <StackPanel x:Name='Parent' Background='Green'>
    <TextBlock HorizontalAlignment='Center'
               Margin='10'
               FontSize='32'>Threading and UI</TextBlock>
    <TextBlock Margin='10'
               FontSize='22'
               TextWrapping='Wrap'>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</TextBlock>
    <Button Content='Change Color'
            Width='150'
            Height='50'
            Margin='10'
            FontSize='22'
            Click='Button_Click'
            x:Name='MyButton'/>
  </StackPanel>
</Window>

代码(C#)

public partial class MainWindow : Window
    {
        private delegate void OneArgumentDelegate(int arg);

        private bool isGreen = true;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            //MyButton.IsEnabled = false;  
            MyButton.Dispatcher.Invoke(() => MyButton.IsEnabled = false);
            /* This starts a background thread from the pool, right?*/
            MyButton.Dispatcher.BeginInvoke(new OneArgumentDelegate(Change_Background_After), DispatcherPriority.Normal, 3000);
        }

        private void Change_Background_After(int delay)
        {
            Thread.Sleep(delay);
            if (isGreen)
            {
                Parent.Background = Brushes.Red;
                isGreen = false;
            }
            else
            {
                Parent.Background = Brushes.Green;
            }
            MyButton.IsEnabled = true;
        }
    }

0 个答案:

没有答案