2013-05-15 70 views
0

我有一个项目,我应该做一个小游戏,在那里你可以将小矩形拖放到网格中,然后填充该网格。 我遇到了问题。制作网格并预先定义大小是没有问题的。但是当现在的网格被填满时,我需要一个不同大小的新网格。在画布上绘制数组WPF C#

然后我记得我曾经用Java创建过的俄罗斯方块游戏,其中网格是使用2d数组创建的,我们可以根据用户输入调整大小。我在重新格式化硬盘时丢失了该项目。

问题是我不知道是否有可能使用WPF和C#在画布上“绘制”一个数组,或者如果有一个简单的方法来创建一个网格,将根据函数调整大小,我会make(该函数并不重要,因为它会根据分数定义行和列的大小)。 我做这个网格作为一个用户控件,并且必须满足以下:

此网格不能大于说,300×300(我可能会使其变大),这意味着该行和collumns应该相应地扩展(如果它是可能)。

当网格已经完成时,我认为我需要拖放到网格中的较小矩形可以由较小的数组构成。然后,当您放下它时,将网格的值从“1”更改为“2”。当网格中的所有地方都充满了“2”,那么你会得到一个新的网格来填充(这是,如果有可能使它与一个阵列)

我真的希望有人能够帮助我,因为我不知道如何做到这一点,唯一能够在互联网上找到的是如何添加拖放到项目。

+0

尺寸调整机制是wpf的优点之一,所以如果你问是否可以做到,那么答案是肯定的,你有什么尝试吗? – makc

+1

你可能想看看[UniformGrid](http://msdn.microsoft.com/en-us/library/ms612624.aspx)。 – Clemens

+0

@ makc不是真的,因为我不知道该怎么做。 –

回答

5

忘记java。这是古老而笨重的,没用的。它甚至没有属性。更不用说WPF提供的DataBinding功能,或者LinQ的美妙之处。

这是我对你所描述的:

<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> 

代码背后:

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); 
     } 
    } 

视图模型:

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); 
     } 
    } 

数据项:

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辅助类):

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)); 
                    })); 
     } 
    } 

结果:

enter image description here

  • 单击并拖动号在左侧并将其拖放到任意正方形。号码将被放置在广场内。
  • 移动滑块并注意UniformGrid的行和列是如何变化的。全部通过DataBinding。
  • 不需要在代码中创建或操作UI元素。全部通过DataBinding完成。
  • 决议独立性。这是WPF提供的。一切都被拉伸到包含的窗口大小。
  • MVVM = “Just Simple,Simple Properties and INotifyPropertyChanged。这就是如何在WPF中编程。不需要复杂的事件“听众”(不管那是什么)或任何这样的糟糕的东西。
  • 只需将我的代码复制并粘贴到File -> New -> WPF Application中即可自行查看结果。
  • 让我知道你是否需要进一步的帮助。
  • WPF Rocks。其他一切都没有或完全吸引。
+0

对不起,我还没有回答:)这几乎是我所期待的。是否有可能取代放入网格的数字,而是将方块放入网格单元中。假设正方形是黑色的,那么当发生下降时,网格单元也会变成黑色。 @HighCore –

+0

@ChristianA你可以通过使用属性和'DataTriggers'或'Bindings'来做任何你想做的事情。只需在“Square”类中放置一个Color属性并将一些“SolidColorBrush.Color”属性绑定到该属性即可。 –

+0

Square类表示一个网格单元格的权利? (只是为了确保我理解正确) –