C# 为什么不';UI元素在按钮单击事件处理程序中反映其状态?
在以下示例中,我如何获得:C# 为什么不';UI元素在按钮单击事件处理程序中反映其状态?,c#,wpf,xaml,event-handling,C#,Wpf,Xaml,Event Handling,在以下示例中,我如何获得: 按钮为“禁用灰色” 要说“正在工作…”的信息 在工作完成时,而不是在工作完成后 XAML: <Window x:Class="TestIsEnabled8938.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="W
- 按钮为“禁用灰色”
- 要说“正在工作…”的信息
<Window x:Class="TestIsEnabled8938.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<StackPanel Margin="10" HorizontalAlignment="Left">
<Button x:Name="Button_Refresh"
HorizontalAlignment="Left"
DockPanel.Dock="Top"
Content="Refresh"
Click="Button_Refresh_Click"
Height="25"
Width="200"/>
<TextBlock x:Name="Message" Text="Button is ready to click."/>
</StackPanel>
</Window>
using System.Windows;
using System.Threading;
namespace TestIsEnabled8938
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Button_Refresh_Click(object sender, RoutedEventArgs e)
{
Message.Text = "working...";
Button_Refresh.IsEnabled = false;
//do work
Thread.Sleep(2000);
Message.Text = "Button is ready to click again.";
Button_Refresh.IsEnabled = true;
}
}
}
这也不起作用:
答复:
感谢Heinzi,此代码有效:
using System.Windows;
using System.Threading;
using System.ComponentModel;
namespace TestIsEnabled8938
{
public partial class Window1 : Window
{
BackgroundWorker backgroundWorker;
public Window1()
{
InitializeComponent();
backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (sender, args) =>
{
Thread.Sleep(3000);
};
backgroundWorker.RunWorkerCompleted += (sender, args) =>
{
Message.Text = "button is ready to click again";
Button_Refresh.IsEnabled = true;
};
}
private void Button_Refresh_Click(object sender, RoutedEventArgs e)
{
Message.Text = "working...";
Button_Refresh.IsEnabled = false;
backgroundWorker.RunWorkerAsync();
}
}
}
您必须在单独的线程上运行任务。一种简单的方法是使用Button.Invoke-method
您必须在单独的线程上运行任务。一种简单的方法是使用Button.Invoke-method
如果希望在任务运行时更新UI(并保持响应),则需要使用单独的线程,例如使用
BackgroundWorker
代码示例(未测试):
如果希望在任务运行时更新UI(并保持响应),则需要使用单独的线程,例如使用
BackgroundWorker
代码示例(未测试):
另一种方法,不管它值多少钱:-
private void Button_Refresh_Click(object sender, RoutedEventArgs e)
{
Message.Text = "working...";
Button_Refresh.IsEnabled = false;
ThreadPool.QueueUserWorkItem(delegate(object state)
{
Thread.Sleep(2000);
Message.Dispatcher.Invoke((Action)delegate()
{
Message.Text = "Button is ready to click again.";
Button_Refresh.IsEnabled = true;
});
});
}
另一种方法,不管它值多少钱:-
private void Button_Refresh_Click(object sender, RoutedEventArgs e)
{
Message.Text = "working...";
Button_Refresh.IsEnabled = false;
ThreadPool.QueueUserWorkItem(delegate(object state)
{
Thread.Sleep(2000);
Message.Dispatcher.Invoke((Action)delegate()
{
Message.Text = "Button is ready to click again.";
Button_Refresh.IsEnabled = true;
});
});
}
不要使用Control.Invoke()-它的内部实现非常糟糕。Invoke()导致一个线程等待另一个线程,因此可能会引入死锁。您应该始终使用BeginInvoke(),它是非阻塞的。不要使用Control.Invoke()-它的内部实现非常糟糕。Invoke()导致一个线程等待另一个线程,因此可能会引入死锁。您应该始终使用BeginInvoke(),它是非阻塞的。没错,我一直在尝试各种Invoke命令,但都不起作用,上面使用Dispatcher的命令会编译,但不会刷新UI。Otherwise I get:System.Windows.Controls.Button'不包含'Invoke'的定义,并且找不到接受'System.Windows.Controls.Button'类型的第一个参数的扩展方法'Invoke'。在WPF中,您必须使用Button.Dispatcher.Invoke()。Button.Invoke()是Winforms。对,我一直在尝试各种Invoke命令,但都不起作用,上面使用Dispatcher的命令编译但不刷新UI。Otherwise I get:System.Windows.Controls.Button'不包含'Invoke'的定义,并且找不到接受'System.Windows.Controls.Button'类型的第一个参数的扩展方法'Invoke'。在WPF中,您必须使用Button.Dispatcher.Invoke()。Invoke()是Winforms。
private void Button_Refresh_Click(object sender, RoutedEventArgs e)
{
Message.Text = "working...";
Button_Refresh.IsEnabled = false;
ThreadPool.QueueUserWorkItem(delegate(object state)
{
Thread.Sleep(2000);
Message.Dispatcher.Invoke((Action)delegate()
{
Message.Text = "Button is ready to click again.";
Button_Refresh.IsEnabled = true;
});
});
}