简体   繁体   中英

C# WPF - How to make object moving with arrow keys using behavior?

I am pretty new to C# and even more new to MVVM, but as i heard it is best what WPF can work with so i am getting myself into. I wanted to start building first, very simple game but i stucked on the very start. Just to mension: i was looking here and there a lot, but i just couldn't make it work. I created rectangle, gave it ship look, and wanted to make it move. This is what I got: C# - Behavior class

using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Shapes;

namespace gierkaPierwszy.Zachowania
{
    public class Zachowania : Behavior<Rectangle>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.PreviewKeyDown += AssociatedObject_PreviewKeyDown; 
    }

        private void AssociatedObject_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            AssociatedObject.Focus();
            switch (e.Key)
            {
                case Key.Left:
                    if (Canvas.GetLeft(AssociatedObject) > 0) Canvas.SetLeft(AssociatedObject, Canvas.GetLeft(AssociatedObject) - 1);
                    break;
                case Key.Right: Canvas.SetLeft(AssociatedObject,Canvas.GetLeft(AssociatedObject) + 1);
                    break;
                case Key.Up:
                    if (Canvas.GetTop(AssociatedObject) > 0) Canvas.SetTop(AssociatedObject, Canvas.GetLeft(AssociatedObject) - 1);
                    break;
                case Key.Down:
                     Canvas.SetTop(AssociatedObject, Canvas.GetTop(AssociatedObject) + 1);
                    break;
                default:
                return;
        }
    }
}

}

Also, as it is pretty important: my xaml code:

<Window x:Class="gierkaPierwszy.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:z="clr-namespace:gierkaPierwszy.Zachowania"
    xmlns:local="clr-namespace:gierkaPierwszy"
    mc:Ignorable="d"
    Title="MainWindow" Height="700" Width="525">
<Canvas>
    <Rectangle x:Name="Board" Width="525" Height="700">
        <Rectangle.Fill>
            <ImageBrush Stretch="Fill" ImageSource="C:\Users\User\Desktop\szkola c#\tło gry.jpg" ></ImageBrush>
        </Rectangle.Fill>
    </Rectangle>
    <Rectangle x:Name="SpaceShip" Width="50" Height="100" RenderTransformOrigin="0.1,0.54" Canvas.Top="400" Canvas.Left="250">
        <i:Interaction.Behaviors>
            <z:Zachowania/>
        </i:Interaction.Behaviors>
        <Rectangle.Fill>
            <ImageBrush Stretch="Fill" ImageSource="C:\Users\User\Desktop\szkola c#\bronie 2d\PNG\Sprites\Ships\spaceShips_006.png" ></ImageBrush>
        </Rectangle.Fill>
    </Rectangle>
</Canvas>

it would be great if someone tell me where i went wrong or help figure out other solution.

Also: Sorry for non-English names in some places, i am getting used to programming standards but sometimes i fail.

Greetings !

KeyEvents and MouseEvents (in short) are sent only to control if it should receive event or its child. You can also create behavior attached to main window or some parent control and create DependencyProperty with target control which will be a "SpaceShip". Then Window can get events and using behavior could move SpaceShip. Your behavior will fail if you have more than one SpaceShip.

using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Shapes;

namespace gierkaPierwszy.Zachowania
{
    public class Zachowania : Behavior<Window>
    {
        public static readonly DependencyProperty SpaceShipProperty 
            = DependencyProperty.Register("SpaceShip", typeof(Rectangle), typeof(Zachowania), new FrameworkPropertyMetadata(null));

        public Rectangle SpaceShip
        {
            set { SetValue(SpaceShipProperty, value); }
            get { return (Rectangle)GetValue(SpaceShipProperty); }
        }

        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.PreviewKeyDown += AssociatedObject_PreviewKeyDown; 
        }

        private void AssociatedObject_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (SpaceShip == null) return;

            switch (e.Key)
            {
                case Key.Left:
                    if (Canvas.GetLeft(SpaceShip) > 0) Canvas.SetLeft(SpaceShip, Canvas.GetLeft(SpaceShip) - 1);
                    break;
                case Key.Right: Canvas.SetLeft(SpaceShip,Canvas.GetLeft(SpaceShip) + 1);
                    break;
                case Key.Up:
                    if (Canvas.GetTop(SpaceShip) > 0) Canvas.SetTop(SpaceShip, Canvas.GetLeft(SpaceShip) - 1);
                    break;
                case Key.Down:
                     Canvas.SetTop(SpaceShip, Canvas.GetTop(SpaceShip) + 1);
                    break;
                default:
                return;
        }
    }
}

Xaml:

<Window x:Class="gierkaPierwszy.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:z="clr-namespace:gierkaPierwszy.Zachowania"
    xmlns:local="clr-namespace:gierkaPierwszy"
    mc:Ignorable="d"
    Title="MainWindow" Height="700" Width="525">
<i:Interaction.Behaviors>
    <z:Zachowania SpaceShip="{Binding ElementName=SpaceShip}"/>
</i:Interaction.Behaviors>
<Canvas>
    <Rectangle x:Name="Board" Width="525" Height="700">
        <Rectangle.Fill>
            <ImageBrush Stretch="Fill" ImageSource="C:\Users\User\Desktop\szkola c#\tło gry.jpg" ></ImageBrush>
        </Rectangle.Fill>
    </Rectangle>
    <Rectangle x:Name="SpaceShip" Width="50" Height="100" RenderTransformOrigin="0.1,0.54" Canvas.Top="400" Canvas.Left="250">
        <Rectangle.Fill>
            <ImageBrush Stretch="Fill" ImageSource="C:\Users\User\Desktop\szkola c#\bronie 2d\PNG\Sprites\Ships\spaceShips_006.png" ></ImageBrush>
        </Rectangle.Fill>
    </Rectangle>
</Canvas>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM