好,所以我花了数小时试图弄清楚为什么它不起作用。我有几个属性可以毫无问题地从视图模型更新视图。但是,当尝试显示默认情况下处于隐藏状态的按钮时,一旦设置了某个属性,平面便拒绝这样做。我将在下面发布相关代码。
App.xaml
<Application.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</Application.Resources>
GameView.xaml
<StackPanel Orientation="Horizontal">
<Button Content="Next Round" FontSize="24" Width="165" Margin="5" Height="80" Click="NextRoundButton_Click" Name="NextRound" Visibility="{Binding IsVisible, Converter={StaticResource BoolToVis}, FallbackValue=Hidden}" />
</StackPanel>
GameViewModel.cs
private bool _isVisibile;
public bool IsVisibile
{
get => _isVisibile;
set
{
_isVisibile = value;
OnPropertyChanged(nameof(IsVisibile));
}
}
<!-- Farther down in the code during checking of win conditions -->
public void CheckGameWinCondition()
{
if (_dealer.CardTotal > 21)
{
_gameBoard.currentGameState = GameBoard.GameState.RoundOver;
_messages = "Dealer Bust";
_player.TotalWinnings = _player.TotalBet * 2;
_player.BankRoll += _player.TotalWinnings;
}
else if (_dealer.CardTotal == 21)
{
_gameBoard.currentGameState = GameBoard.GameState.RoundOver;
_messages = "Dealer BlackJack";
}
else if (_player.CardTotal > _dealer.CardTotal)
{
_gameBoard.currentGameState = GameBoard.GameState.RoundOver;
_messages = "Player Won";
_player.TotalWinnings = _player.TotalBet * 2;
_player.BankRoll += _player.TotalWinnings;
}
else if (_player.CardTotal < _dealer.CardTotal)
{
_gameBoard.currentGameState = GameBoard.GameState.RoundOver;
_messages = "Dealer Won";
}
else if (_player.CardTotal == _dealer.CardTotal)
{
_gameBoard.currentGameState = GameBoard.GameState.RoundOver;
_messages = "Draw";
_player.TotalWinnings = _player.TotalBet;
_player.BankRoll += _player.TotalWinnings;
}
else
{
_messages = "Error";
OnPropertyChanged(nameof(Messages));
}
_isVisibile = _gameBoard.Visible();
OnPropertyChanged(nameof(IsVisibile));
OnPropertyChanged(nameof(Dealer));
OnPropertyChanged(nameof(Player));
OnPropertyChanged(nameof(Messages));
}
这里的错误错误else语句只是存根,而不是最终代码。
GameBoard.cs
public bool Visible()
{
if (currentGameState == GameState.RoundOver)
{
return true;
}
else
{
return false;
}
}
所以我有从我的ObservableObject类继承的GameViewModel。这对于我的所有其他绑定都很好,包括在整个UI中切换其他按钮上的IsEnabled。就像我所有其他按钮和事件一样,它也已编码,因此应该可以正常工作。调试显示_isVisible的值已设置为true,因为我在调用GameBoard类中的Visibility()方法返回true或false之前将currentGameState设置为GameBoard.GameState.RoundOver。
它应该进行转换,但不是。我从字面上看了关于此问题的近100条帖子。我已经尝试了遇到的所有内容,尽管OnPropertyChanged()正在按预期方式触发,但没有任何更新。
使用按钮命令不是一种选择,因为这是我为上课而开发的游戏,并且这是我尝试在自己身上添加的一项额外功能。因此,这不是功课,而是游戏正在进行中。我只想隐藏“新回合”按钮,直到回合结束,然后出现它,以便用户可以单击它并开始下一只手。我尝试将转换器也放在Window.Resources下的GameView.xaml中,但仍然无法正常工作。
任何帮助将不胜感激。我们的老师特别希望我们在单击按钮时从ViewModel后面的代码中调用方法,而不是执行命令,以免在学习WPF时使事情变得更复杂。因此,为什么我不希望使用命令,也不想为该项目在这种情况下它们会有所帮助。预先感谢您查看此内容,并希望发现我正在做的一些愚蠢的事情。
如果您需要更多我没有发布的代码的详细信息,可以在我的GitHub https://github.com/petersteele111/WPF_BlackJack上完整查看代码。
对于它的价值,我发现使用ICommand
对象比将Observable
属性绑定到按钮的Visibility
或IsEnabled
属性要可靠得多。我几乎不再直接绑定IsEnabled
或Visibility
属性。
您将需要this class来实现命令:
/// <summary>
/// Josh Smith's implementation of RelayCommand. See https://gist.github.com/schuster-rainer/2648922
/// </summary>
public class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute) : this(execute, null) { }
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute ?? throw new ArgumentNullException("execute");
_canExecute = canExecute;
}
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion
}
在您的GameViewModel.cs
中,放置此端点:
private ICommand _nextRoundCommand;
public ICommand NextRoundCommand
{
get
{
if (_nextRoundCommand== null)
_nextRoundCommand= new RelayCommand(x => NextRound(), y => IsVisible);
return _nextRoundCommand;
}
}
public void NextRound()
{
// Implementation goes here.
}
然后像这样钩上您的按钮:
<Button
Name="NextRound"
Width="165"
Height="80"
Margin="5"
Command="{Binding NextRoundCommand}"
Content="Next Round"
FontSize="24"/>
Command
对象旨在绑定到按钮的IsEnabled
属性。要使按钮在IsVisible
属性为false时消失而不是禁用,可以向其中添加this trigger:
<Button
Name="NextRound"
Width="165"
Height="80"
Margin="5"
Command="{Binding NextRoundCommand}"
Content="Next Round"
FontSize="24">
<Button.Style>
<Style TargetType="{x:Type Button}" >
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>