2013-05-15 73 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類表示一個網格單元格的權利? (只是爲了確保我理解正確) –