我有一個組合框和一個按鈕。我希望每當我從中選擇一項時,該按鈕不會被禁用
XAML:
<Border Style="{StaticResource borderMain}"
Grid.Row="7"
Grid.Column="0">
<ComboBox ItemsSource="{Binding Source={StaticResource portNames}}"
SelectedItem="{Binding SelectedPort, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
x:Name="Port_Selector" Grid.Column="0"
Text="Port Selector" Background="White"/>
</Border>
<Border Style="{StaticResource borderMain}"
Grid.Column="1"
Grid.Row="7">
<Button Content="Connect"
Command="{Binding OpenPortCommand}"
CommandParameter="{Binding SelectedPort}"
Style="{StaticResource buttonMain}"
Margin="5"/>
</Border>
命令 :
public class OpenPortCommand : ICommand
{
public OpenPortVM OpenPortVM{ get; set; }
public OpenPortCommand(OpenPortVM OpenPortVM)
{
this.OpenPortVM = OpenPortVM;
}
public event EventHandler? CanExecuteChanged
{
add { CommandManager.RequerySuggested = value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object? parameter)
{
string? portCom = parameter as string;
if (!string.IsNullOrEmpty(portCom))
return true;
return false;
}
public void Execute(object? parameter)
{
OpenPortVM.ConnectPort();
}
}
我已經除錯它并檢查我用于系結的變數SelectedPort的值,它上面有一個值,但不知何故,我的按鈕的 CommandParameter 未檢測到,因此CanExecute方法無法正常運行。我錯過了什么嗎?
更新
預期的 :

結果:

更新 2
Setter 上的斷點:

斷點在 CanExecute

uj5u.com熱心網友回復:
您OpenPortCommand錯過了實際引發CanExecuteChanged事件的可能性。我建議如下:
public class OpenPortCommand : ICommand
{
public OpenPortVM OpenPortVM{ get; set; }
public OpenPortCommand(OpenPortVM OpenPortVM)
{
this.OpenPortVM = OpenPortVM;
}
// Leave this event as is, don't do an explicit implementation
public event EventHandler? CanExecuteChanged;
public void RaiseCanExecuteChange() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
public bool CanExecute(object? parameter) => !string.IsNullOrEmpty(parameter as string);
// rest ommitted
}
在您的 ViewModel 的SelectedPort屬性中:
public string SelectedPort
{
get => _selectedPort;
set
{
_selectedPort = value;
// call your OnPropertyChanged( ... );
OpenPortCommand?.RaiseCanExecuteChanged();
}
}
在 XAML 中,我簡化了ComboBox.SelectedItem屬性的系結,如下所示:
<ComboBox ... SelectedItem="{Binding SelectedPort}"/>
uj5u.com熱心網友回復:
您的代碼有兩個問題:
- 實際上阻??止您的代碼正確執行的最關鍵的是您引發
INotifyPropertyChanged.PropertyChanged事件的方式。您當前不是傳入屬性名稱,而是傳入支持欄位的名稱。
代替
OnPropertyChanged(nameof(portSelected));
肯定是
OnPropertyChanged(nameof(SelectedPort));
為了簡化事件呼叫,您的呼叫者應該使用以下CallerMemberName屬性:
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
=> this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName);
然后OnPropertyChanged不帶任何引數呼叫該方法,因為現在會自動檢測屬性名稱:
OnPropertyChanged();
- 該方法
RaiseExecuteChangedCommand是多余的。您ICommand的CanExecuteChanged事件實作將事件處理程式委托給CommandManager.RequerySuggested事件(這是正確的)。該CommandManager.RequerySuggested事件由 WPF 框架自動引發,并且由于事件委托,框架也會引發ICommand.CanExecuteChanged(因為您使用 將所有ICommand.CanExecuteChanged處理程式附加到CommandManager.RequerySuggested事件CommandManager.RequerySuggested = value)。如果您不希望框架為您引發 CanExecuteChanged 事件,則必須洗掉該CommandManager.RequerySuggested = value部分,即不要將客戶端處理程式附加到CommandManager.RequerySuggested事件。因為現在您將從您的RaiseExecuteChangedCommand方法中明確提出它。所以你不能兩者兼得。要么ICommand.CanExecuteChanged明確加注,要么讓CommandManager他們為你做。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/357652.html
