Andrew Sklyar
Andrew Sklyar

Reputation: 293

WPF Adding Image as Content to Button doesn't work

I am trying to create image 15-puzzle game, where you have to combine the image by sliding the squares. Almost everything works correctly, except that instead of showing the image inside a button it shows it as a text "System.Drawing.Image".

Here is my MainWindow.xaml.cs code:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Collections;
using static System.Math;
using System.Collections.Generic;
using System.Drawing;
using Image = System.Drawing.Image;
using Brushes = System.Windows.Media.Brushes;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace Quizz
{

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    //Array of buttons
    private static readonly List<Button> Buttons = new List<Button>(15);

    // Position of an empty space
    private static int _xPos;
    private static int _yPos;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        for (var i = 0; i < 15; i++)
        {
            Buttons.Add(new Button() { Background = Brushes.AliceBlue });
        }
        _xPos = new Random(int.Parse(Guid.NewGuid().ToString().Substring(0, 8), System.Globalization.NumberStyles.HexNumber)).Next(3);
        _yPos = new Random(int.Parse(Guid.NewGuid().ToString().Substring(0, 8), System.Globalization.NumberStyles.HexNumber)).Next(3);
        CreateDynamicWpfGrid();
    }

    private void CreateDynamicWpfGrid()
    {
        // Create the Grid
        var dynamicGrid = new Grid { ShowGridLines = true };

        // Create Columns
        var gridCol1 = new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) };
        var gridCol2 = new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) };
        var gridCol3 = new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) };
        var gridCol4 = new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) };
        dynamicGrid.ColumnDefinitions.Add(gridCol1);
        dynamicGrid.ColumnDefinitions.Add(gridCol2);
        dynamicGrid.ColumnDefinitions.Add(gridCol3);
        dynamicGrid.ColumnDefinitions.Add(gridCol4);

        // Create Rows
        var gridRow1 = new RowDefinition { Height = new GridLength(1, GridUnitType.Star) };
        var gridRow2 = new RowDefinition { Height = new GridLength(1, GridUnitType.Star) };
        var gridRow3 = new RowDefinition { Height = new GridLength(1, GridUnitType.Star) };
        var gridRow4 = new RowDefinition { Height = new GridLength(1, GridUnitType.Star) };
        dynamicGrid.RowDefinitions.Add(gridRow1);
        dynamicGrid.RowDefinitions.Add(gridRow2);
        dynamicGrid.RowDefinitions.Add(gridRow3);
        dynamicGrid.RowDefinitions.Add(gridRow4);


        // Bind Buttons and Grid Cells
        int j = 0;
        var imgList = Randomizer();
        for (var i = 0; i < 16; i++)
        {
            if (i % 4 != _xPos || _yPos != i / 4)
            {
                //Add image in a button
                Buttons[j].Content = imgList[j];
                Buttons[j].Click += Button_Click;
                Grid.SetColumn(Buttons[j], i%4);
                Grid.SetRow(Buttons[j], i/4);
                dynamicGrid.Children.Add(Buttons[j]);
                j++;
            }
        }
        // Display grid into a Window
        RootWindow.Content = dynamicGrid;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var button = (Button)sender;
        var x = Grid.GetColumn(button);
        var y = Grid.GetRow(button);
        if ((Abs(_xPos - x) != 1 || Abs(_yPos - y) != 0) && (Abs(_yPos - y) != 1 || Abs(_xPos - x) != 0)) return;
        Grid.SetColumn(button, _xPos);
        Grid.SetRow(button, _yPos);
        _xPos = x;
        _yPos = y;
    }

    private List<Image> Randomizer()
    {
        var imageList = CropImage();
        var randomImageList = new List<Image>(15);
        for (var i = 0; i < 15; i++)
        {
            var pos = new Random(int.Parse(Guid.NewGuid().ToString().Substring(0, 8), System.Globalization.NumberStyles.HexNumber)).Next(imageList.Count);
            randomImageList.Add(imageList[pos]);
            imageList.RemoveAt(pos);
        }
        return randomImageList;
    }

    private Bitmap ResizeImage(Image image)
    {
        var destRect = new Rectangle(0, 0, (int)RootWindow.Width ,(int) RootWindow.Height );
        var destImage = new Bitmap((int)RootWindow.Width, (int)RootWindow.Height);

        destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

        using (var graphics = Graphics.FromImage(destImage))
        {
            graphics.CompositingMode = CompositingMode.SourceCopy;
            graphics.CompositingQuality = CompositingQuality.HighQuality;
            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphics.SmoothingMode = SmoothingMode.HighQuality;
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

            using (var wrapMode = new ImageAttributes())
            {
                wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
            }
        }

        return destImage;
    }

    private List<Image> CropImage()
    {
        var imgList = new List<Image>(16);
        var img = (Image)ResizeImage(Image.FromFile(@"D:\Documents\Шаг\Программы WPF\Quizz\Quizz\Resources\Image.jpeg"));

        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                var index = i * 4 + j;
                imgList.Add(new Bitmap(80, 80));
                var graphics = Graphics.FromImage(imgList[index]);
                graphics.DrawImage(img, new Rectangle(0, 0, 80, 80), new Rectangle(i * 80, j * 80, 80, 80), GraphicsUnit.Pixel);
                graphics.Dispose();
            }
        }
        imgList.RemoveAt(imgList.Count - 1);
        return imgList;
    }
}
}

Here is my MainWindow.xaml code:

<Window x:Class="Quizz.MainWindow"
    Title="Пятнашки"       Icon="pack://application:,,,/Quizz;component/resources/Icon.ico"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="320" Width="320"
    Name="RootWindow" ResizeMode="NoResize"
    Loaded="MainWindow_Loaded">
</Window>

What am I doing wrong??

Upvotes: 0

Views: 192

Answers (1)

Dylan
Dylan

Reputation: 1118

Here is what I did to get this to work.

I created a list of StackPanels similar to your button list.

private static readonly List<StackPanel> StackPanels = new List<StackPanel>(15);

then populated the list like you did the buttons..

private static readonly List<StackPanel> StackPanels = new List<StackPanel>(15);

Then Here is the for loop with the fix in the CreateDynamicWPFGrid method. Added the Stack panel to the content and added the Image to the stack panel after converting it to a Control.Image.

        // Bind Buttons and Grid Cells
        int j = 0;
        var imgList = Randomizer();
        for (var i = 0; i < 16; i++)
        {
            if (i % 4 != _xPos || _yPos != i / 4)
            {
                //Add image in a button

                var bitmapImage = new BitmapImage();
                var bitmap = imgList[j];

                using (var memoryStream = new MemoryStream())
                {
                    bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Bmp);
                    bitmapImage.BeginInit();
                    bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                    bitmapImage.StreamSource = memoryStream;
                    bitmapImage.EndInit();
                }

                var image = new System.Windows.Controls.Image
                {
                    Source = bitmapImage,
                    Stretch = Stretch.None
                };

                var currentstack = StackPanels[j];
                currentstack.Orientation = Orientation.Horizontal;

                currentstack.Children.Add(image);
                Buttons[j].Content = currentstack;

                Buttons[j].Click += Button_Click;
                Grid.SetColumn(Buttons[j], i % 4);
                Grid.SetRow(Buttons[j], i / 4);
                dynamicGrid.Children.Add(Buttons[j]);
                j++;
            }
        }

Upvotes: 1

Related Questions