0

I would like to use ICommand to change the Paddle1.Y int value of my ViewModel. Am I supposed to create a class implementing ICommand interface? I have done that. But since it is a class, it doesn't have access to my ViewModel's Paddle1 property without creating a property for it. I would prefer to create the command within my ViewModel for this reason. At this point I'm trying to pass the Paddle1 to the Command as a CommandParameter in XAML. I am failing at this, and I'm not sure it is the cleanest approach to editing the state of my ViewModel either.

Could I get a code example of my UpKeyPressed command being bound to either a button or the keyboard up key? With no CommandParameter would be more clean, if the command could access my ViewModel Paddle1 property.

My ViewModel:

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;
    }
}

My XAML page that uses the viewmodel as a 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>

Data structure of my solution

enter image description here

My attempt to fix:

    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 attempt (no errors but not workling upon pressing the 'O' key):

<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>

Ben
  • 259
  • 1
  • 3
  • 14
  • you have just 1 method `UpKeyPressed` in your view-model, it cannot be used for binding. You need to declare a property. Also the `UpKeyPressed` command should have some property accepting your `Paddle1`, and you need to set that property at the time initializing the command in your view-model class. – King King Oct 13 '15 at 02:14
  • @KingKing Do you mean I create a property in my ViewModel of type UpKeyPressed and I create a property in my UpKeyPressed class called Paddle1 and I give the class a constructor which sets the Paddle1 property? – Ben Oct 13 '15 at 02:47
  • something like that but you should set the `Paddle1` property right after init your command (normally in the `getter` of the `UpKeyPressed` property) – King King Oct 13 '15 at 02:52
  • @KingKing I have attempted to fix and pasted it into the question. Not working yet. Cheers. – Ben Oct 13 '15 at 03:11

1 Answers1

0

Looked at your attempt, there are some things we need to be fix, first your CanExecute should not involve the parameter anymore:

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

Secondly your XAML binding is wrong, you already have DataContext of your view-model flown in your visual tree, you just need a simple Binding with some Path specified like this:

<KeyBinding Command="{Binding DoSomethingCommand}" 
            Key="O" 
            Modifiers="Control"/>
King King
  • 61,710
  • 16
  • 105
  • 130
  • Thanks. I have a break point in the execute method of the UpKeyPressed class and it still doesn't fire when the "o" key is pressed. There is no error displaying. – Ben Oct 13 '15 at 03:32
  • @Ben I've just tested it and confirm that it should work. Do you have any `DataContext` set to something different in code behind? – King King Oct 13 '15 at 03:48
  • This is my codebehind: `public partial class GamePlayView : Window { public GamePlayView() { InitializeComponent(); DataContext = new GamePlayViewModel(); } }` – Ben Oct 13 '15 at 03:55
  • Can you see in the ***Output*** window to check if there is any exception thrown silently there? – King King Oct 13 '15 at 03:58
  • I have " Cannot find or open the PDB file." for about 5 dll files. – Ben Oct 13 '15 at 04:02
  • well looks like that's a big problem (and of course does not involve what I answered here). You need to check your ***References*** of the project, if you have some dependency dll (and still opened in some project), try re-building them first,... – King King Oct 13 '15 at 04:04
  • Wait, looks like it's just a message saying that you cannot debug into the referenced dll (due to lacking of PDB file), so you can ignore those messages. Try scanning it again for any other kind of error message? See here http://stackoverflow.com/questions/15937707/error-message-cannot-find-or-open-the-pdb-file – King King Oct 13 '15 at 04:07
  • @Ben looks like you have separate dll for your `GamePlayViewModel`, you cannot hope the execution to jump in `Execute` in a referenced dll ***unless*** you re-build that dll with some `Debug` option. Try openning your dll project property, select `Build` tab, look in the `Debug info:` field and set it to `full`. Re-build that dll. After that you can debug that dll from your current project. – King King Oct 13 '15 at 04:10
  • Thanks. There are no other errors. A few hours ago I had a command working with a button click and not with a key press. I think for some reason the key press doesn't work. I'm sure if I turned it into a button click it would work. – Ben Oct 13 '15 at 04:10
  • @Ben read my comment above, it actually works, the problem is that you cannot debug the referenced dll without any Debug info. – King King Oct 13 '15 at 04:13
  • I also print to the console in the command which does not happen. We can ignore the debugger and use the print instead. – Ben Oct 13 '15 at 04:13
  • The dlls that cannot be found are not for any of the projects that I wrote – Ben Oct 13 '15 at 04:20
  • looks like you have a very strange and tough problem. Again I would like to confirm that I ***copied and pasted your exact code*** and tested it on my side, it worked perfectly. If possible, please update your question with your ***actual*** code. – King King Oct 13 '15 at 04:20
  • I just pasted my final code into the part of my question that says "my attempt to fix" – Ben Oct 13 '15 at 04:24
  • @Ben well, how did you actually test the code? I hope you pressed `Ctrl + O`, not just `O` (because I saw you said `not workling upon pressing the 'O' key`). – King King Oct 13 '15 at 04:26
  • I wasn't pressing ctrl. It works when I press ctrl. Why must I press ctrl? I want the user to play the game without pressing ctrl. – Ben Oct 13 '15 at 04:28
  • @Ben so just remove `Modifiers="Control"` – King King Oct 13 '15 at 04:29
  • Haha. That's what happens when you don't understand all the code that you copy paste. My Bad. Thanks. – Ben Oct 13 '15 at 04:31