【问题标题】:Grid animation (button color change)网格动画(按钮颜色变化)
【发布时间】:2017-01-03 12:59:30
【问题描述】:

我想在我的网格中创建一个动画。我有一个 5x5 网格,每个网格显示一个按钮。加载网格后,其中一个按钮应随机将其颜色更改为绿色。 1 秒后,此按钮应变回原状,另一个应将其颜色变为绿色。

如果用户能够在这 1 秒内用鼠标(鼠标悬停)到达此按钮,则该按钮应将其颜色更改为红色并保持红色。下一个将颜色变为绿色的按钮不应该是这个。

这应该是一个小游戏。我的问题是,实现这个游戏的最简单方法是什么。

请帮帮我!

<Page x:Class="LeapTest.Layout"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:local="clr-namespace:LeapTest"
  mc:Ignorable="d" 
  d:DesignHeight="1050" d:DesignWidth="1000"
  Title="Layout">

<Page.Resources>
    <Style x:Key="pageTitle" TargetType="TextBlock">
        <Setter Property="Background" Value="DimGray"/>
        <Setter Property="FontSize"  Value="40"/>
        <Setter Property="FontFamily"  Value="Arial"/>
        <Setter Property="TextAlignment" Value="Center"/>
        <Setter Property="Padding" Value="0,5,0,5"/>
    </Style>

    <Style x:Key="Grid" TargetType="Grid">
        <Setter Property="Background" Value="White"/>
    </Style>

    <Style x:Key="Button" TargetType="Button">
        <Setter Property="Background" Value="White"/>
        <Setter Property="BorderBrush" Value="Green"/>
        <Setter Property="BorderThickness" Value="2"/>
    </Style>

</Page.Resources>

<Grid Style="{StaticResource Grid}">
    <Grid.RowDefinitions>
        <RowDefinition Height="50" />
        <RowDefinition Height="200" />
        <RowDefinition Height="200" />
        <RowDefinition Height="200" />
        <RowDefinition Height="200" />
        <RowDefinition Height="200" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200" />
        <ColumnDefinition Width="200" />
        <ColumnDefinition Width="200" />
        <ColumnDefinition Width="200" />
        <ColumnDefinition Width="200" />
    </Grid.ColumnDefinitions>

    <TextBlock Grid.Column="0" Grid.ColumnSpan="5" Style="{StaticResource pageTitle}"> LEAP Motion </TextBlock>

    <Button Name ="BTN_0_0" Grid.Column="0" Grid.Row="1" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_0_1" Grid.Column="1" Grid.Row="1" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_0_2" Grid.Column="2" Grid.Row="1" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_0_3" Grid.Column="3" Grid.Row="1" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_0_4" Grid.Column="4" Grid.Row="1" Click="BTN_Click" Style="{StaticResource Button}"/>

    <Button Name ="BTN_1_0" Grid.Column="0" Grid.Row="2" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_1_1" Grid.Column="1" Grid.Row="2" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_1_2" Grid.Column="2" Grid.Row="2" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_1_3" Grid.Column="3" Grid.Row="2" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_1_4" Grid.Column="4" Grid.Row="2" Click="BTN_Click" Style="{StaticResource Button}"/>

    <Button Name ="BTN_2_0" Grid.Column="0" Grid.Row="3" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_2_1" Grid.Column="1" Grid.Row="3" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_2_2" Grid.Column="2" Grid.Row="3" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_2_3" Grid.Column="3" Grid.Row="3" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_2_4" Grid.Column="4" Grid.Row="3" Click="BTN_Click" Style="{StaticResource Button}"/>

    <Button Name ="BTN_3_0" Grid.Column="0" Grid.Row="4" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_3_1" Grid.Column="1" Grid.Row="4" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_3_2" Grid.Column="2" Grid.Row="4" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_3_3" Grid.Column="3" Grid.Row="4" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_3_4" Grid.Column="4" Grid.Row="4" Click="BTN_Click" Style="{StaticResource Button}"/>

    <Button Name ="BTN_4_0" Grid.Column="0" Grid.Row="5" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_4_1" Grid.Column="1" Grid.Row="5" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_4_2" Grid.Column="2" Grid.Row="5" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_4_3" Grid.Column="3" Grid.Row="5" Click="BTN_Click" Style="{StaticResource Button}"/>
    <Button Name ="BTN_4_4" Grid.Column="4" Grid.Row="5" Click="BTN_Click" Style="{StaticResource Button}"/>

</Grid>

//BackEnd Code
      private void BTN_Click(object sender, RoutedEventArgs e)
    {
        //BTN1.Background = Brushes.Green;

        Button btnTest = (Button)sender;
        if (btnTest.Background == Brushes.Green)
        {
            btnTest.Background = Brushes.White;
        }
        else
        {
            btnTest.Background = Brushes.Green;
        }
    }

【问题讨论】:

  • 你的代码后端是什么?你试过什么?
  • 后端代码确实很有趣,您也可以使用模板创建网格/按钮(绑定到值或简单模型的后备列表),这应该会清理您的代码很多跨度>
  • 我使用 Visual Studio 进行编程,并且我已经尝试使用情节提要......但由于不同的原因失败了。其中之一是我不知道如何在没有鼠标事件的情况下启动动画
  • 你需要什么帮助我?
  • 后端代码,最有用的是至少 BTN_Click 做了什么

标签: c# wpf animation mouseover


【解决方案1】:

您应该使用特殊名称或标签遍历表单上的所有按钮控件。将其保存在一个数组中并随机选择一个并更改它的颜色。如果鼠标悬停找到具有正确颜色的那个,则调用随机查找控件的方法,依此类推。

这应该很简单。因为这看起来像家庭作业。我不会为你解决它,因为你不会学到任何东西。想想需要做什么,然后分别谷歌搜索每个部分。试着理解它然后继续!祝你好运!

【讨论】:

    【解决方案2】:

    编辑:关于您的问题,严格来说,您不需要动画来实现您想要做的事情,除非您需要动画颜色变化。

    这是一个完整的工作示例不使用 MVVM,而是使用代表按钮的模型集合。

    处理所有逻辑(随机、模型更改等)的主窗口/页面代码:

    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private const int BTN_NUMBERS = 25;
        private ObservableCollection<ButtonModel> _buttonsCollection;
        private ButtonModel _currentTarget;
    
        public ObservableCollection<int> ExcludedItems
        {
            get { return _excludedItems; }
            private set { _excludedItems = value; OnPropertyChanged(); }
        }
    
        private Random _rnd;
        private Timer _timer;
        private ObservableCollection<int> _excludedItems = new ObservableCollection<int>();
    
        public MainWindow()
        {
            DataContext = this;
    
            InitializeComponent();
            ButtonsCollection = new ObservableCollection<ButtonModel>();
            for (int i = 0; i < BTN_NUMBERS; i++)
            {
                ButtonsCollection.Add(new ButtonModel() { ButtonNumber = i });
            }
    
            Start();
        }
    
        private void Start()
        {
            _currentTarget = null;
            foreach (var bm in ButtonsCollection)
            {
                bm.IsCurrentTarget = bm.IsReached = false;
            }
            ExcludedItems.Clear();
            _rnd = new Random(DateTime.Now.Second);
            _timer = new Timer(OnTargetChanged, null, 0, 1000);
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        public ObservableCollection<ButtonModel> ButtonsCollection
        {
            get { return _buttonsCollection; }
            set { _buttonsCollection = value; OnPropertyChanged(); }
        }
    
        void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
        private void Btn_candidate_OnMouseEnter(object sender, MouseEventArgs e)
        {
            ButtonModel model = ((Button)sender).DataContext as ButtonModel;
            if (model != null && model.IsCurrentTarget && !ExcludedItems.Contains(model.ButtonNumber))
            {
                model.IsReached = true;
                ExcludedItems.Add(model.ButtonNumber);
            }
        }
    
        private void ChangeTarget()
        {
            var target = GetNextTarget();
            if (target == -1)
            {
    
                if (_timer != null)
                {
                    _timer.Dispose();
                    _timer = null;
                }
                MessageBox.Show("All items have been reached ! Congratulations");
            }
            if (_currentTarget != null) _currentTarget.IsCurrentTarget = false;
            _currentTarget = ButtonsCollection[target];
            _currentTarget.IsCurrentTarget = true;
        }
    
        private int GetNextTarget()
        {
            if (ExcludedItems.Count == BTN_NUMBERS)
            {
                return -1;
            }
            var target = _rnd.Next(0, BTN_NUMBERS);
            if (ExcludedItems.Contains(target))
            {
                return GetNextTarget();
            }
            return target;
        }
    
        private void OnTargetChanged(object state)
        {
            this.Dispatcher.InvokeAsync(ChangeTarget);
        }
    
        private void Btn_startover_OnClick(object sender, RoutedEventArgs e)
        {
            Start();
        }
    }
    

    代表按钮的模型,包含触发 XAML 更改的代码:

        public class ButtonModel : INotifyPropertyChanged
    {
        private bool _isCurrentTarget;
        private bool _isReached;
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        public int ButtonNumber { get; set; }
    
        public bool IsCurrentTarget
        {
            get { return _isCurrentTarget; }
            set { _isCurrentTarget = value; OnPropertyChanged(); }
        }
    
        public bool IsReached
        {
            get { return _isReached; }
            set { _isReached = value; OnPropertyChanged(); }
        }
    
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    最后,也是最重要的,简化的 XAML 代码:

    <Window x:Class="GridAnimame.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:local="clr-namespace:GridAnimame"
        mc:Ignorable="d"
        d:DataContext="{d:DesignInstance {x:Type local:MainWindow}}"
        Title="MainWindow" Height="500" Width="500">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="400"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="400"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <ItemsControl ItemsSource="{Binding ButtonsCollection}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Name="btn_candidate"  MouseEnter="Btn_candidate_OnMouseEnter" Margin="1">
                        <Button.Template>
                            <ControlTemplate TargetType="Button">
                                <Border x:Name="brd_btn_layout" Background="LightGray" BorderBrush="Black" BorderThickness="1">
                                    <TextBlock Text="{Binding ButtonNumber}" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"></TextBlock>
                                </Border>
                                <ControlTemplate.Triggers>
                                    <DataTrigger Binding="{Binding IsCurrentTarget}" Value="true">
                                        <Setter TargetName="brd_btn_layout" Property="Background" Value="Green"></Setter>
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding IsReached}" Value="true">
                                        <Setter TargetName="brd_btn_layout" Property="Background" Value="Red"></Setter>
                                    </DataTrigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Button.Template>
                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    
        <ListBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding ExcludedItems}"></ListBox>
    
        <Button x:Name="btn_startover" Grid.Row="1" Grid.Column="1" Content="Start Over !" Margin="2" Click="Btn_startover_OnClick"></Button>
    </Grid>
    

    虽然逻辑可以改进,但这里是这个示例的关键点:

    • 您不会在 XAML 中以静态方式声明所有按钮。相反,您的主模型包含代表按钮的模型集合,并包含将触发 XAML(视觉)更改的所有数据。因此,XAML 中表示网格的控件绑定到此集合

    • 逻辑是通过代码实现的,这个逻辑的视觉效果通过在 XAML 中声明的触发器来体现

    • 1234563应该替换为 DelegateCommands

    【讨论】:

      猜你喜欢
      • 2014-12-02
      • 1970-01-01
      • 2016-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-15
      • 2014-01-19
      • 1970-01-01
      相关资源
      最近更新 更多