2009-06-05 9 views
7

私はWPFの新機能ですから、文法などを学ぶために非常に単純なメモリカードゲームを始めました。ゲームでは、すべてのカードが下を向いているところに2枚ひっくり返し、一致する場合はそれを取り除きます。そうでない場合は下に置き換えて、最も短い枚数のカードをすべて取り除こうとします。私が言ったように、非常に単純な... :)WPFのテーブルレイアウト

私の質問は、HTMLのような表要素がないので、余白を混乱させるのではなく、均一なレイアウトで簡単にカードを置くことができますか?

答えて

10

Matt Hamiltonが提案したUniformGridを使用した例です。

まず、使用するクラスとデータを作成します。 各カードは、カードオブジェクトによって表され、顔特性を持つことになります。

public class Card 
{ 
    public string Face { get; set; } 
    public Card() { } 
} 

次に、我々は、カードのコレクションを持つクラスを必要とし、また、私たちは、カードの数を設定することができますプロパティます。 CardCollectionでは、ObservableCollectionを使用できます。これは、カードの追加または削除時に自動的にUIに通知するためです。 NumberOfCardsプロパティには、UIに通知する独自のメソッドが必要です。このためにはimplementINotifyPropertyChangedインターフェイスを使用できます。我々はまた、使用する行/列の数を表すプロパティをお勧めします、これは私たちのNumberOfCardsの平方根になります。

public class Cards : INotifyPropertyChanged 
{ 
    private int myNumberOfCards; 
    public int NumberOfCards 
    { 
     get { return this.myNumberOfCards; } 
     set 
     { 
      this.myNumberOfCards = value; 
      NotifyPropertyChanged("NumberOfCards"); 

      // Logic is going in here since this is just an example, 
      // Though I would not recomend hevily modifying the setters in a finalized app. 
      while (this.myNumberOfCards > CardCollection.Count) 
      { 
       CardCollection.Add(new Card { Face = (CardCollection.Count + 1).ToString() }); 
      } 
      while (this.myNumberOfCards < CardCollection.Count) 
      { 
       CardCollection.RemoveAt(CardCollection.Count - 1); 
      } 

      NotifyPropertyChanged("CardColumns"); 
     } 
    } 
    public int CardColumns 
    { 
     get 
     { 
      return (int)Math.Ceiling((Math.Sqrt((double)CardCollection.Count))); 
     } 
    } 
    private ObservableCollection<Card> myCardCollection; 
    public ObservableCollection<Card> CardCollection 
    { 
     get 
     { 
      if (this.myCardCollection == null) 
      { this.myCardCollection = new ObservableCollection<Card>(); } 
      return this.myCardCollection; 
     } 
    } 
    public Cards(int initalCards) 
    { 
     NumberOfCards = initalCards; 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 

    #endregion 
} 


最後に、私たちは窓に私たちのDataContextとしてこれを設定することができますXAMLのCardsクラスにバインドします。 XAMLの場合、単純なItemsControlを使用して選択できないようにし、DataTemplateをボタンに設定して、各カードをクリックできるようにしました。私は見てお勧めします

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     InitializeComponent(); 
     this.DataContext = new Cards(25); 
    } 
} 

<Window x:Class="Sample_BoolAnimation.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" 
    Height="300" 
    Width="300"> 
    <Grid> 
     <DockPanel> 
      <DockPanel DockPanel.Dock="Top"> 
       <TextBlock Text="Number of Cards:" /> 
       <TextBox Text="{Binding NumberOfCards, UpdateSourceTrigger=PropertyChanged}" /> 
      </DockPanel> 
      <ItemsControl ItemsSource="{Binding CardCollection}"> 
       <ItemsControl.ItemsPanel> 
        <ItemsPanelTemplate> 
         <UniformGrid Columns="{Binding CardColumns}" /> 
        </ItemsPanelTemplate> 
       </ItemsControl.ItemsPanel> 
       <ItemsControl.ItemTemplate> 
        <DataTemplate> 
         <Button Content="{Binding Face}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 

        </DataTemplate> 
       </ItemsControl.ItemTemplate> 
      </ItemsControl> 
     </DockPanel> 
    </Grid> 
</Window> 

もう一つは、ジョシュ・スミスのContentControl3D実装です。それで、あなたはCardクラスで実装するためにあなたが探しているように、ふさわしい振る舞いを与えることができます。

+0

非常に良い! +1 ...これが「受け入れられる」ことを願っています! –

+0

ああこれは素晴らしいです、ありがとうございます! –

2

あなたのシナリオではUniformGridをお勧めします。クイック検索にはthis articleがあり、これにはいくつかのコードとスクリーンショットが含まれています。

+0

UniformGridの最も優れた部分は、ItemsControlのItemsPanelを使用してそれを使用できるように設定できることです。次に、カードをItemsSorceでバインドし、XAMLで各カードを宣言する必要はありません。 – rmoore

+0

私はXAMLに静的なカード数を持たずに、遊びたいカードの数をユーザに尋ねてから、それらを生成するつもりでした。 ItemsControl/ItemSourceの記事がありますか? –

+0

@rmooreは話せませんが、ListBoxのItemsPanelとしてUniformGridを使うことについて話しています。ここでWrapPanelと似たようなことをする記事があります:http://compilewith.net/2008/03/wpf-listbox-itemspaneltemplate-and.html –

0

WPFにはテーブルがあります。ここでは、それを使い始めるにあたっては、articleをお勧めします。経験からWPFのテーブルは使いやすく、グリッドの使用は一般的にはより良い選択肢です。

+1

TableオブジェクトはTextBlocksおよびFlowDocumentsで使用され、UI要素はそれほど多くはありません。 – YotaXP

関連する問題