gpt4 book ai didi

WPF:无法使用命令绑定(bind)和线程控制按钮的启用/禁用状态

转载 作者:行者123 更新时间:2023-12-04 14:32:51 25 4
gpt4 key购买 nike

我有一个 WPF 应用程序,它只包含一个按钮和一个文本框来显示一些输出。当用户单击按钮时,会启动一个禁用按钮的线程,将内容打印到输出文本框,然后线程停止(此时我希望再次启用按钮)。

该应用程序似乎正确禁用了按钮,并正确更新了文本框。但是,当线程完成时,它总是无法正确地重新启用按钮!谁能告诉我我做错了什么?

这是我的 xaml 的片段:

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" HorizontalAlignment="Center" Command="{Binding ExecuteCommand}">E_xecute</Button>
<Label Grid.Row="1" Content="Output Window:" HorizontalAlignment="Left"/>
<TextBlock Grid.Row="2" Text="{Binding Output}"/>
</Grid>

这是我的 ViewModel 代码(我使用的是 Josh Smith 的 MVVM 设计):
public class WindowViewModel : ViewModelBase
{
private bool _threadStopped;
private RelayCommand _executeCommand;
private string _output;

public WindowViewModel()
{
_threadStopped = true;
}

public string Output { get { return _output; } set { _output = value; OnPropertyChanged("Output"); } }

public ICommand ExecuteCommand
{
get
{
if (_executeCommand == null)
{
_executeCommand = new RelayCommand(p => this.ExecuteThread(p), p => this.CanExecuteThread);
}
return _executeCommand;
}
}

public bool CanExecuteThread
{
get
{
return _threadStopped;
}
set
{
_threadStopped = value;
}
}

private void ExecuteThread(object p)
{
ThreadStart ts = new ThreadStart(ThreadMethod);
Thread t = new Thread(ts);
t.Start();
}

private void ThreadMethod()
{
CanExecuteThread = false;
Output = string.Empty;
Output += "Thread Started: Is the 'Execute' button disabled?\r\n";
int countdown = 5000;

while (countdown > 0)
{
Output += string.Format("Time remaining: {0}...\r\n", countdown / 1000);
countdown -= 1000;
Thread.Sleep(1000);
}
CanExecuteThread = true;
Output += "Thread Stopped: Is the 'Execute' button enabled?\r\n";
}
}

最佳答案

您需要帮助 WPF 知道命令的可执行状态已更改。执行此操作的简单方法是:

CommandManager.InvalidateRequerySuggested()

在 CanExecuteThread 内部:
set
{
_threadStopped = value;
CommandManager.InvalidateRequerySuggested()
}

编辑(现在我有时间了):实际问题很可能是您在 CanExecuteThread 时没有通知属性变化。它应该提高 PropertyChanged为了让 WPF 检测到更改:
public bool CanExecuteThread
{
get { return _threadStopped; }
set
{
if (_threadStopped != value)
{
_threadStopped = value;
this.OnPropertyChanged(() => this.CanExecuteThread);
}
}
}

以上假设您的 ViewModel基类有 OnPropertyChanged方法。

也就是说,我还想指出,您可以通过简单地使用 BackgroundWorker 来简化事情。 :
public class WindowViewModel : ViewModel
{
private readonly BackgroundWorker backgroundWorker;

public WindowVieWModel()
{
backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += delegate
{
// do work here (what's currently in ThreadMethod)
};
backgroundWorker.RunWorkerCompleted += delegate
{
// this will all run on the UI thread after the work is done
this.OnPropertyChanged(() => this.CanExecuteThread);
};
}

...

public bool CanExecuteThread
{
get { !this.backgroundWorker.IsBusy; }
}

private void ExecuteThread(object p)
{
// this will kick off the work
this.backgroundWorker.RunWorkerAsync();

// this property will have changed because the worker is busy
this.OnPropertyChanged(() => this.CanExecuteThread);
}
}

您可以进一步重构它以使其更好,但您明白了。

关于WPF:无法使用命令绑定(bind)和线程控制按钮的启用/禁用状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3390525/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com