18907

Draw array on canvas WPF C# [closed]

Question:

I have a project where i'm supposed to make a little game, where you can drag and drop small rectangles into a grid, and then fill that grid. I have run into a problem. It's no problem making a grid and define the size in advance. But I need a new grid in a different size when the current grid has been filled.

I then remembered a tetris game i once made in Java, where the grid was created using a 2d array, that we were able to resize depending on user input. I lost the project during a reformat of my HDD.

The problem is i don't know if it's possible to "draw" an array on a canvas using WPF and C#, or if there is an easy way to make a grid that will be sized according to a function I will make (the function is not important, since it will define the row and collumn size depending on a score). I have made this grid as a usercontrol, and the following must apply:

This grid cannot be larger than say 300 x 300 ( i might make it larger ) which means that the rows and collumns should scale accordingly (if it's possible).

When the grid has been made, I thought the smaller rectangles i need to drag and drop into the grid, could be made of smaller arrays. Then when you drop it, you change the value of the grid from say "1" to "2". When all places in the grid is filled with "2", then you get a new grid to fill (this is, if it's possible to make it with an array)

I really hope someone is able to help me, since I have no idea how to do this, and the only thing i can find on the internet is how to add drag and drop to items.

Answer1:

Forget java. It's old and clunky and useless. It doesn't even have properties. Let alone the <a href="http://msdn.microsoft.com/en-us/library/ms752347.aspx" rel="nofollow">DataBinding</a> capabilities WPF provides, or the awesome beauty that is LinQ.

This is my take on what you described:

<Window x:Class="MiscSamples.SquaresGameSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Forget java. It's a crappy dinousaur." Height="300" Width="300"> <DockPanel> <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="2"> <TextBlock Text="Rows:"/> <Slider Maximum="100" Minimum="10" Value="{Binding Rows}" Width="200"/> <TextBlock Text="Columns:"/> <Slider Maximum="100" Minimum="10" Value="{Binding Columns}" Width="200"/> </StackPanel> <ListBox Margin="0,0,20,0" Width="50" DockPanel.Dock="Left" ItemsSource="{Binding Numbers}"> <ListBox.ItemContainerStyle> <Style TargetType="ListBoxItem"> <EventSetter Event="PreviewMouseLeftButtonDown" Handler="OnItemMouseDown"/> </Style> </ListBox.ItemContainerStyle> </ListBox> <ItemsControl ItemsSource="{Binding Squares}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <UniformGrid Rows="{Binding Rows}" Columns="{Binding Columns}"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <Border BorderBrush="DarkGray" BorderThickness="1" Background="#05FFFFFF" AllowDrop="True" Drop="OnDrop"> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding Value}"/> </Border> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </DockPanel> </Window>

Code Behind:

public partial class SquaresGameSample : Window { public SquaresGameSample() { InitializeComponent(); DataContext = new SquaresGameViewModel(); } private void OnDrop(object sender, DragEventArgs e) { var item = sender as FrameworkElement; if (item == null) return; var square = item.DataContext as Square; if (square == null) return; var number = (int)e.Data.GetData(typeof (int)); square.Value = number; } private void OnItemMouseDown(object sender, MouseEventArgs e) { var item = sender as ListBoxItem; if (item == null) return; DragDrop.DoDragDrop(sender as DependencyObject, item.DataContext, DragDropEffects.Move); } }

ViewModel:

public class SquaresGameViewModel: PropertyChangedBase { private ObservableCollection<Square> _squares; public ObservableCollection<Square> Squares { get { return _squares ?? (_squares = new ObservableCollection<Square>()); } } private int _rows; public int Rows { get { return _rows; } set { _rows = value; OnPropertyChanged("Rows"); CreateSquares(); } } private int _columns; public int Columns { get { return _columns; } set { _columns = value; OnPropertyChanged("Columns"); CreateSquares(); } } public List<int> Numbers { get; set; } public SquaresGameViewModel() { _rows = 10; _columns = 10; Numbers = Enumerable.Range(1, 20).ToList(); CreateSquares(); } private void CreateSquares() { Squares.Clear(); Enumerable.Range(0, Rows) .SelectMany(x => Enumerable.Range(0, Columns) .Select(y => new Square { Row = x, Column = y })) .ToList().ForEach(Squares.Add); } }

Data Item:

public class Square: PropertyChangedBase { public int Row { get; set; } public int Column { get; set; } private int _value; public int Value { get { return _value; } set { _value = value; OnPropertyChanged("Value"); } } }

PropertyChangedBase (MVVM Helper class):

public class PropertyChangedBase:INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { Application.Current.Dispatcher.BeginInvoke((Action) (() => { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); })); } }

Result:

<img alt="enter image description here" class="b-lazy" data-src="https://i.stack.imgur.com/iSiyB.png" data-original="https://i.stack.imgur.com/iSiyB.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" />

<ul><li>Click and drag the numbers in the left side and drop them on any square. The Number will be placed inside the Square.</li> <li>Move the Sliders around and notice how the UniformGrid's Rows and Columns change. All via DataBinding.</li> <li>There's no need to create or manipulate UI elements in code. All is done via DataBinding.</li> <li>Resolution Independence. This is what WPF provides. Everything is stretched to the containing Window Size.</li> <li>MVVM = <em>"Just Simple, Simple Properties and INotifyPropertyChanged"</em>. That's how to program in WPF. No need for complex event "Listeners" (whatever that is) or any crappy stuff like that.</li> <li>Just copy and paste my code in a File -> New -> WPF Application and see the results for yourself.</li> <li>Let me know if you need further assistance.</li> <li>WPF Rocks. Everything else either does not or completely sucks.</li> </ul>

Recommend

  • WPF routed command enabling works with menu but not with a button
  • regarding WPF validation;
  • KeyBinding woes
  • Clr namespace mapping to default xaml namespaces
  • Styling ListBoxItem's of nested ListBoxes [WPF]
  • How to align text in a WPF menu item?
  • WPF MVVM WinformsHost with OpenGL-Control
  • UWP Template 10 create a dynamic hamburgermenu
  • WPF8/C# - Binding Data To Grid
  • Detaching entity along with referenced entities
  • Why does CollectionViewSource.GetDefaultView(…) return the wrong CurrentItem from inside a Task thre
  • Powerpoint 2010 VSTO AddIn taskpane on multiple Windows
  • Complex Silverlight TreeView, is nested hierarchy possible?
  • Keep transition effect on 1 div from moving the div that follows?
  • Multibinding Multiselection ListView
  • Updating one element of a bound Observable collection
  • How to convert WPF project so it can be used as a class library by a separate exe
  • Android Lock Screen C# .NET Replica
  • Running jasmine tests for a component with NgZone dependency
  • How to resolve permission denied maybe missing internet permission?
  • powershell Get-Counter -ComputerName parameter on Windows 7
  • Xamarin MonoAndroid Azure mobile service InsertAsync
  • WPF Template Binding in ToggleButton UserControl
  • WP8.1 AppBarButton holding event
  • Private IP address in reserved subnet range
  • How To Customize ASP.NET Chart Databound To SqlDataSource
  • Android - Material Design - NavigationView - How to put vertical scroll?
  • MongoDB in PHP using aggregate to group by _id is null not working
  • Display issues when we change from one jquery mobile page to another in firefox
  • To display the title for the current loaction in map in iphone
  • bootstrap to use multiple ng-app
  • How to get icons for entities from eclipse?
  • trying to dynamically update Highchart column chart but series undefined
  • Can Visual Studio XAML designer handle font family names with spaces as a resource?
  • Turn off referential integrity in Derby? is it possible?
  • JaxB to read class hierarchy
  • Observable and ngFor in Angular 2
  • How to Embed XSL into XML
  • UserPrincipal.Current returns apppool on IIS
  • Conditional In-Line CSS for IE and Others?