簡體   English   中英

如何在WPF中將布爾數組綁定到矩形網格的可見性屬性?

[英]How to bind a boolean array to the visibility properties of a grid of rectangles in WPF?

我正在嘗試使用矩形網格在WPF中制作一個簡單的蛇游戲。 我已經或多或少地完成了蛇的邏輯處理,但是我對如何實際可視化布爾值的二維數組(無論像素(矩形)是否可見)感到困惑。 這個問題解決了如何將可見性視為布爾值,但是我將如何擴展呢?

下面的代碼描述了蛇的移動,我的目標是在單獨的線程中運行其Update方法。 它通過將SnakeBod對象添加到具有age屬性的列表來工作。 當Age超過一定數量時,Update方法將停止將其視為現有對象。 我的目標是通過KeyDown事件控制蛇。

問題是:如何將二維VisibleBods數組綁定到MainWindow中的64x64網格上?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace SnakeGame
{
    static class Snake
    {
        static public int SnakeLife;
        static public List<SnakeBod> SnakeBods;
        static SnakePos headPos;
        static public bool[,] VisibleBods = new bool[64, 64];
        internal static SnakePos HeadPos
        {
            get => headPos;
            set
            {
                if (headPos.X != value.X || headPos.Y != value.Y)
                {
                    if (headPos.X > 64 || headPos.X < 0 || headPos.Y > 64 || headPos.X < 0) SnakeLife = -1;
                    bool exists = false;
                    headPos = value;
                    foreach (SnakeBod curBod in SnakeBods)
                    {
                        if (curBod.BodPos.X == value.X && curBod.BodPos.Y == value.Y)
                        {
                            exists = true;
                            if (curBod.age > SnakeLife) curBod.age = 0;
                            else SnakeLife = -1;
                        }
                    }
                    if (!exists) SnakeBods.Add(new SnakeBod(value.X, value.Y));
                }
            }
        }


        static int snakeWait;
        static Direction SnakeDir;
        enum Direction : int
        {
            LEFT = 0,
            UP = 1,
            RIGHT = 2,
            DOWN = 3,
        }

        static Snake()
        {
            headPos = new SnakePos(32, 32);
            for (int i = 0; i < 64; i++)
            {
                for (int j = 0; j < 64; j++)
                {
                    VisibleBods[i, j] = false;
                }
            }
            SnakeLife = 10;
        }

        static void UpdateBod()
        {
            for (int i = 0; i < 64; i++)
            {
                for (int j = 0; j < 64; j++)
                {
                    VisibleBods[i, j] = false;
                }
            }
            foreach (SnakeBod curBod in SnakeBods)
            {
                if (curBod.age < SnakeLife) VisibleBods[curBod.BodPos.X, curBod.BodPos.Y] = true;
            }

        }

        static Thread UpdateThread;
        static void UpdateSnake()
        {
            Thread.CurrentThread.IsBackground = true;
            while (SnakeLife > 0)
            {
                switch (SnakeDir)
                {
                    case Direction.LEFT:
                        HeadPos = new SnakePos(HeadPos.X - 1, HeadPos.Y);
                        break;
                    case Direction.UP:
                        HeadPos = new SnakePos(HeadPos.X, HeadPos.Y - 1);
                        break;
                    case Direction.RIGHT:
                        HeadPos = new SnakePos(HeadPos.X + 1, HeadPos.Y);
                        break;
                    case Direction.DOWN:
                        HeadPos = new SnakePos(HeadPos.X, HeadPos.Y + 1);
                        break;
                }
                foreach (SnakeBod curBod in SnakeBods)
                {
                    curBod.age++;
                }
                Thread.Sleep(snakeWait);
            }
        }
    }

    class Crumb
    {

    }

    class SnakeBod
    {
        public SnakePos BodPos;
        public int age;
        public SnakeBod(int xIn, int yIn)
        {
            age = 0;
            BodPos.X = xIn;
            BodPos.Y = yIn;
        }
    }

    internal struct SnakePos
    {
        public int X;
        public int Y;

        public SnakePos(int xIn, int yIn)
        {
            X = xIn;
            Y = yIn;
        }
    }
}

編輯:我也知道此codeproject ,但我想以自己的方式嘗試。 通常,我主要在XAML中進行綁定,並且由於這是大規模的,所以我認為必須在Codebehind中完成。 最大的障礙之一是如何綁定到ViewModel內部的數組元素,就像設置普通字段時我只調用OnPropertyChanged()一樣。

我看到的最簡單的解決方案是完全避免使用[,]數組:

public MyType[] RegularArray { get { return ReduceArrayDimensionality(TwoDimensionalArray); } }

您可以繼續進行討厭的.Linq擴展,以更美觀的方式實現該目標,我相信.SelectMany(array => array).ToArray()可以做到。

這樣,您的綁定便成為常規綁定。 您唯一需要關心的是適當的BooleanToWahteverYouLikeConverter : IValueConverter這個人是WPF綁定系統附帶的一部分。 您可以找到許多教程和示例。 您的轉換器必須足夠聰明,以找出這次要考慮的確切布爾boolean 使用ConverterParameter傳遞必要的索引。

而已。

吻。

為了在單元格網格中的單個單元格的可見性更改時更新UI,您應該實現標准的MVVM方法,即使用實現INotifyPropertyChanged的項類將ItemsControl綁定到單元格項的集合:

public class Cell : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private bool isVisible;
    public bool IsVisible
    {
        get { return isVisible; }
        set
        {
            if (isVisible != value)
            {
                isVisible = value;
                PropertyChanged?.Invoke(this,
                    new PropertyChangedEventArgs(nameof(IsVisible)));
            }
        }
    }
}

public class ViewModel
{
    public List<Cell> Cells { get; } =
        Enumerable.Range(0, 4096).Select(i => new Cell()).ToList();
}

ItemsControl將使用UniformGrid來顯示單元格:

<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>
<Grid>
    <ItemsControl ItemsSource="{Binding Cells}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid Columns="64"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Rectangle Width="10" Height="10" Fill="Green"
                           Visibility="{Binding IsVisible,
                               Converter={StaticResource BooleanToVisibilityConverter}}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

更改單元格的可見性:

((ViewModel)DataContext).Cells[index].IsVisible = true;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM