[英]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.