将 Image-Source 绑定到 C# 的位置
Posted
技术标签:
【中文标题】将 Image-Source 绑定到 C# 的位置【英文标题】:Binding Image-Source to position of piece C# 【发布时间】:2020-09-21 18:18:33 【问题描述】:情况:我正在开发一个国际象棋游戏,用户可以在其中移动棋盘上的棋子。 该板包含 8x8 字段 (=64),就像普通的一样。
板子:板子是一个动态创建的 Grid,有 8 行 8 列。每个“字段”都包含另一个 Grid,该 Grid 包含一个 Rectangle(=使用 fill 属性的字段颜色)和一个 Image(=字段上的块的图像 [块或空])。
我想做什么:我想将图像的源属性绑定到任何一块的位置。
示例:当任何一块的位置发生变化时,图像会自动移除旧的源(因为该块已移开)&块现在所在的字段,更新图像源。 需要明确的是:我在 (1,1)||(A,1) 有一个棋子并将其移动到 (1,2)||(A,2)。现在旧位置 (1,1)||(A,1) 的图像源应设置为空,因为棋子已移动,新位置字段的图像源应设置为“pawn.png ”。
现在的工作原理:目前我在图片上有一个点击事件。当注册第一次点击事件时,我保存点击的图像(=ref)并等待第二次点击。当注册第二次点击时,我将第二次点击的图片的来源设置为第一次点击的图片的来源,并将第一次点击的图片的来源设置为空来源......但这不是一个好的解决方案......
问题:如何绑定 64 个图像源,以便将 32 个图像的每个位置变化都通知给 UI?
这里是ChessField类:
public class ChessField : INotifyPropertyChanged
public int X get; protected set;
public int Y get; protected set;
public bool Recheable
get;
set;
private readonly SolidColorBrush _defaultFieldColor;
public ChessField(int X, int Y, SolidColorBrush fieldColor)
this.X = X;
this.Y = Y;
ColorProperty = fieldColor;
_defaultFieldColor = fieldColor;
Recheable = false;
public void SetToDefault()
ColorProperty = _defaultFieldColor;
Recheable = false;
private SolidColorBrush colorProperty;
public SolidColorBrush ColorProperty
get
return colorProperty;
set
if (colorProperty == value) return;
colorProperty = value;
OnPropertyChanged();
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
PiecePos 是一个结构体,如下所示:
public struct PiecePos
public int X get; set;
public int Y get; set;
public PiecePos(int X, int Y)
this.X = X;
this.Y = Y;
public override bool Equals(object obj)
if (!(obj is PiecePos))
return false;
PiecePos toCompare = (PiecePos)obj;
return (this.X == toCompare.X) && (this.Y == toCompare.Y);
任何帮助将不胜感激!谢谢
【问题讨论】:
你的问题更像是你应该如何构建你的程序,而不是一个 WPF 特定的问题。 我的程序已经构建并运行。问题是:如何绑定 64 张图像,以便我的作品的任何位置变化都会通知 UI?...希望这会有所帮助 使用ImageSource
属性扩展您的 Piece
并将其绑定到 UI(正如您已经使用 EPieceColor
所做的那样)。
在我看来,您可以通过将字段对象与片段对象分开来帮助自己。与其让场对象包含或不包含棋子对象,不如让棋子对象在棋盘上有一个位置,从而可以改变棋子对象的位置。然后你以后可以使用鼠标在棋盘上移动棋子(通过使用 dragStarted、DragDelta 和 DragCompleted 事件)
@AdrianEfford - 很高兴你解决了你的问题。另外,您发现我的想法很有用。我想看看你是如何解决你的问题的
【参考方案1】:
经过一些工作,我解决了这个问题...
解决方案:
-
向 ChessField-Class 添加 ImageSource 属性
为 ChessField-Class 构造函数添加默认值
在动态创建图像的地方进行绑定
ChessField 应如下所示:
public class ChessField : INotifyPropertyChanged
public int X get; protected set;
public int Y get; protected set;
public bool Recheable
get;
set;
private readonly SolidColorBrush _defaultFieldColor;
public ChessField(int X, int Y, SolidColorBrush fieldColor, ImageSource imageSource)
this.X = X;
this.Y = Y;
ColorProperty = fieldColor;
_defaultFieldColor = fieldColor;
this.ImageSource = imageSource;
Recheable = false;
public void SetToDefault()
ColorProperty = _defaultFieldColor;
Recheable = false;
private SolidColorBrush colorProperty;
public SolidColorBrush ColorProperty
get
return colorProperty;
set
if (colorProperty == value) return;
colorProperty = value;
OnPropertyChanged();
private ImageSource imageSource;
public ImageSource ImageSource
get return imageSource;
set
if (imageSource == value) return;
imageSource = value;
OnPropertyChanged();
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
这里如何动态创建图像并将它们添加到 UI:
private void CreateImages()
ChessField chessField = new ChessField(X, Y, defaultColor, startImage); //Create field
//Each field is a single grid
Grid fieldGrid = new Grid();
fieldGrid.SetValue(Grid.RowProperty, Helper.BoardSize - Y);
fieldGrid.SetValue(Grid.ColumnProperty, X - 1);
Image imageField = new Image();
imageField.MouseDown += ImageClickEvent; //Click event
imageField.HorizontalAlignment = HorizontalAlignment.Stretch;
imageField.VerticalAlignment = VerticalAlignment.Stretch;
imageField.Tag = x + "," + y; //Set the image tag (needed for the click event)
imageField.DataContext = chessField;
imageField.SetBinding(Image.SourceProperty, "ImageSource"); //Binding
_chessFields.Add(chessField); //Add to list --> so we can access the field on the click event
fieldGrid.Children.Add(imageField);
BoardGrid.Children.Add(fieldGrid); //Add field-grid to the main-grid in the XAML
图片点击事件:
private void ImageClickEvent()
//Move to
var pieceToMove = Board.PiecesOnTheBoard
.FirstOrDefault(piece => piece.Position.X == _lastSelectedField.X && piece.Position.Y == _lastSelectedField.Y && piece.IsAlive);
var oldField = _chessFields.FirstOrDefault(field =>
field.X == pieceToMove.Position.X && field.Y == pieceToMove.Position.Y);
pieceToMove?.Move(new PiecePos(clickedChessField.X, clickedChessField.Y)); //Move
var newField = _chessFields.FirstOrDefault(field =>
field.X == pieceToMove?.Position.X && field.Y == pieceToMove.Position.Y);
if (oldField != null)
oldField.ImageSource = Helper.EmptyImage; //Use binding to change image
if (newField != null)
newField.ImageSource = pieceToMove?.GetImage(); //Use binding to change image
【讨论】:
很好 :) - 您按照计划解决了问题。好工作。但我仍然认为你应该考虑对象以及它们如何交互:)以上是关于将 Image-Source 绑定到 C# 的位置的主要内容,如果未能解决你的问题,请参考以下文章
如何将 DataGridViewComboBoxColumn 绑定到 OnChange 事件(C#)