将 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#)

C#如何将网页绑定到本地的某个端口上

将实体框架对象绑定到 Datagridview C#

C# 将 DataTable 绑定到现有 DataGridView 列定义

c# 组合框绑定到对象列表

C# 类属性“绑定”到文件? (见 Perl::Tie)