私はWPFの新機能ですから、文法などを学ぶために非常に単純なメモリカードゲームを始めました。ゲームでは、すべてのカードが下を向いているところに2枚ひっくり返し、一致する場合はそれを取り除きます。そうでない場合は下に置き換えて、最も短い枚数のカードをすべて取り除こうとします。私が言ったように、非常に単純な... :)WPFのテーブルレイアウト
私の質問は、HTMLのような表要素がないので、余白を混乱させるのではなく、均一なレイアウトで簡単にカードを置くことができますか?
私はWPFの新機能ですから、文法などを学ぶために非常に単純なメモリカードゲームを始めました。ゲームでは、すべてのカードが下を向いているところに2枚ひっくり返し、一致する場合はそれを取り除きます。そうでない場合は下に置き換えて、最も短い枚数のカードをすべて取り除こうとします。私が言ったように、非常に単純な... :)WPFのテーブルレイアウト
私の質問は、HTMLのような表要素がないので、余白を混乱させるのではなく、均一なレイアウトで簡単にカードを置くことができますか?
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クラスで実装するためにあなたが探しているように、ふさわしい振る舞いを与えることができます。
あなたのシナリオではUniformGridをお勧めします。クイック検索にはthis articleがあり、これにはいくつかのコードとスクリーンショットが含まれています。
UniformGridの最も優れた部分は、ItemsControlのItemsPanelを使用してそれを使用できるように設定できることです。次に、カードをItemsSorceでバインドし、XAMLで各カードを宣言する必要はありません。 – rmoore
私はXAMLに静的なカード数を持たずに、遊びたいカードの数をユーザに尋ねてから、それらを生成するつもりでした。 ItemsControl/ItemSourceの記事がありますか? –
@rmooreは話せませんが、ListBoxのItemsPanelとしてUniformGridを使うことについて話しています。ここでWrapPanelと似たようなことをする記事があります:http://compilewith.net/2008/03/wpf-listbox-itemspaneltemplate-and.html –
非常に良い! +1 ...これが「受け入れられる」ことを願っています! –
ああこれは素晴らしいです、ありがとうございます! –