您遇到的问题是您尝试在不应该使用的地方使用 DataBinding。
我不同意您在发布的链接中获得的其他答案。虽然 ControlTemplate 解决方案看起来很整洁,但它们并没有解决您的问题的核心,也就是说,您正在尝试使用单个控件(复选框)来做两件不同的事情:显示状态(例如选中/未选中) 并执行逻辑(远程设备等)。
ControlTemplates 旨在更改控件的显示方式,但不改变其行为方式。你试图改变行为,而不是外表。请参阅“什么是 ControlTemplate?” 在这里了解更多详情
为此,您将不得不存储一些放弃标准绑定并处理一些事件:
XAML:
<Window x:Class="WPFCheckBoxClickTester.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">
<Grid>
<CheckBox x:Name="foo" Checked="foo_Checked"></CheckBox>
</Grid>
</Window>
代码隐藏:
using System.ComponentModel;
using System.Threading;
using System.Windows;
namespace WPFCheckBoxClickTester
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private BackgroundWorker _worker = new BackgroundWorker();
public Window1()
{
InitializeComponent();
foo.IsThreeState = false;
this._worker.DoWork += new DoWorkEventHandler(_worker_DoWork);
this._worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_worker_RunWorkerCompleted);
}
private void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
foo.IsChecked = true;
foo.IsEnabled = true;
return;
}
private void _worker_DoWork(object sender, DoWorkEventArgs e)
{
Thread.Sleep(500);
return;
}
private void foo_Checked(object sender, RoutedEventArgs e)
{
if( foo.IsChecked == true && this.foo.IsEnabled )
{
this.foo.IsChecked = false;
this.foo.IsEnabled = false;
this._worker.RunWorkerAsync();
}
return;
}
}
}
上面的代码示例使您能够通过 BackgroundWorker 异步执行一些代码——我已将 Thread.Sleep 作为占位符放入。我还在 foo_Checked 中使用 foo.IsEnabled 作为标记值,但您可能需要一些额外的状态来处理所有情况(例如,从 Checked 变为 Unchecked)。