【问题标题】:Use ICommand to change the state of the ViewModel使用 ICommand 改变 ViewModel 的状态
【发布时间】:2015-10-13 01:59:44
【问题描述】:

我想使用 ICommand 更改我的 ViewModel 的 Paddle1.Y int 值。我应该创建一个实现 ICommand 接口的类吗?我已经做到了。但由于它是一个类,因此如果不为其创建属性,它就无法访问我的 ViewModel 的 Paddle1 属性。出于这个原因,我更愿意在我的 ViewModel 中创建命令。此时,我试图将 Paddle1 作为 XAML 中的 CommandParameter 传递给 Command。我在这方面失败了,我也不确定这是否是编辑我的 ViewModel 状态的最干净的方法。

我能否获得一个将 UpKeyPressed 命令绑定到按钮或键盘向上键的代码示例?如果命令可以访问我的 ViewModel Paddle1 属性,那么没有 CommandParameter 会更干净。

我的视图模型:

namespace Pong.Core.ViewModels
{
    public class GamePlayViewModel
    {
        private readonly Paddle Paddle1;
        private Paddle Paddle2;

        public GamePlayViewModel()
        {
            Paddle1 = new Paddle();
            Paddle2 = new Paddle();
            UpKeyPressed();
        }

        public ICommand UpKeyPressed()
        {
            var r = new UpKeyPressed();
            r.Execute(Paddle1);
            return r;
        }
    }

    public class UpKeyPressed : ICommand
    {
        public void Execute(object parameter)
        {
            var paddle = parameter as Paddle;
            Debug.Assert(paddle != null, "paddle != null");
            paddle.IncreaseY();
            Debug.WriteLine(paddle.Y);
        }

        public bool CanExecute(object parameter)
        {
            return parameter != null;
        }
        public event EventHandler CanExecuteChanged;
    }
}

我的 XAML 页面使用 viewmodel 作为 dataContext:

<Window x:Class="Pong.Windows.Views.GamePlayView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Pong.Core.ViewModels;assembly=Pong.Core"
        Title="GamePlayView" Height="350" Width="525">
    <Grid>

        <Button CommandParameter="{Binding ElementName=Paddle1}" 
                Command="{StaticResource UpKeyPressed}"  >
            Click
        </Button>


    </Grid>
    <Window.DataContext>
        <local:GamePlayViewModel/>
    </Window.DataContext>
    <Window.InputBindings>
        <KeyBinding Command="{Binding Path=UpKeyPressed}" 
                Key="O" 
                Modifiers="Control"/>
    </Window.InputBindings>
</Window>

我的解决方案的数据结构

我尝试修复:

    namespace Pong.Core.ViewModels
{
    public class GamePlayViewModel
    {
        private readonly Paddle Paddle1;
        private Paddle Paddle2;

        private ICommand _doSomething;

        public ICommand DoSomethingCommand
        {
            get
            {
                if (_doSomething == null)
                {
                    _doSomething = new UpKeyPressed(Paddle1);
                }
                return _doSomething;
            }
        }


        public GamePlayViewModel()
        {
            Paddle1 = new Paddle();
            Paddle2 = new Paddle();
        }
    }

    public class UpKeyPressed : ICommand
    {
        private Paddle Paddle1;

        public UpKeyPressed(Paddle paddle)
        {
            Paddle1 = paddle;
        }

        public void Execute(object parameter)
        {
            //var paddle = parameter as Paddle;
            //Debug.Assert(paddle != null, "paddle != null");
            //paddle.IncreaseY();
            Paddle1.IncreaseY();
            //Debug.WriteLine(paddle.Y);
            Debug.WriteLine(Paddle1.Y);
        }

        public bool CanExecute(object parameter)
        {
            return Paddle1 != null;
        }

        public event EventHandler CanExecuteChanged;
    }
}

XAML 尝试(没有错误,但在按下“O”键时不起作用):

<Window x:Class="Pong.Windows.Views.GamePlayView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewModels="clr-namespace:Pong.Core.ViewModels;assembly=Pong.Core"
    Title="GamePlayView" Height="350" Width="525">
<Grid>


</Grid>
<Window.DataContext>
    <viewModels:GamePlayViewModel/>
</Window.DataContext>
<Window.InputBindings>
    <KeyBinding Command="{Binding DoSomethingCommand}" 
        Key="O" 
        Modifiers="Control"/>
</Window.InputBindings>

【问题讨论】:

  • 您的视图模型中只有 1 个方法 UpKeyPressed,它不能用于绑定。您需要声明一个属性。此外,UpKeyPressed 命令应该有一些属性接受您的Paddle1,并且您需要在视图模型类中初始化命令时设置该属性。
  • @KingKing 你的意思是我在我的 ViewModel 中创建了一个 UpKeyPressed 类型的属性,我在我的 UpKeyPressed 类中创建了一个名为 Paddle1 的属性,并为该类提供了一个设置 Paddle1 属性的构造函数?
  • 类似的东西,但您应该在初始化命令后立即设置Paddle1 属性(通常在UpKeyPressed 属性的getter 中)
  • @KingKing 我已尝试修复并将其粘贴到问题中。还没有工作。干杯。

标签: c# wpf mvvm data-binding icommand


【解决方案1】:

看了你的尝试,有些事情我们需要解决,首先你的CanExecute不应该再涉及parameter

public bool CanExecute(object parameter) {
   return Paddle1 != null;
}

其次,您的 XAML 绑定是错误的,您的视图模型的 DataContext 已经在您的可视化树中飞行,您只需要一个简单的绑定,其中指定了一些路径,如下所示:

<KeyBinding Command="{Binding DoSomethingCommand}" 
            Key="O" 
            Modifiers="Control"/>

【讨论】:

  • 谢谢。我在 UpKeyPressed 类的执行方法中有一个断点,当按下“o”键时它仍然不会触发。没有错误显示。
  • @Ben 我刚刚对其进行了测试并确认它应该可以工作。你有没有任何 DataContext 设置为不同的代码背后的东西?
  • 这是我的代码隐藏:public partial class GamePlayView : Window { public GamePlayView() { InitializeComponent(); DataContext = new GamePlayViewModel(); } }
  • 你能在 Output 窗口中查看是否有无提示抛出的异常吗?
  • 我有“无法找到或打开 PDB 文件。”大约 5 个 dll 文件。
猜你喜欢
  • 2012-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-13
  • 2021-02-10
  • 2017-01-01
  • 2019-07-19
  • 1970-01-01
相关资源
最近更新 更多