WPF中的表布局

jb.*_*jb. 7 wpf

我是WPF的新手,所以我刚开始制作一个非常简单的记忆卡游戏,只是为了学习语法等等.游戏是所有卡面朝下的地方,你翻转两个,如果匹配则将它们移除,否则将它们重新折叠并尝试以最短的翻转次数移除所有卡片.就像我说的,很简单...... :)

我的问题是,HTML中是否没有表格元素,所以我可以轻松地将卡片放在统一的布局中而不必乱用边距?

rmo*_*ore 10

这是使用UniformGrid的一个例子,正如Matt Hamilton建议的那样.

首先,让我们创建我们将要使用的类和数据.每张卡都将由Card对象表示,并具有Face属性:

public class Card
{
    public string Face { get; set; }
    public Card() { }
}
Run Code Online (Sandbox Code Playgroud)

接下来,我们需要一个包含我们的卡片集合的类,以及一个允许我们设置卡片数量的属性.对于CardCollection,我们可以使用ObservableCollection,因为当添加或删除卡时,它会自动通知UI.该NumberOfCards属性将需要它自己的方式来通知用户界面,为此,我们可以实现INotifyPropertyChanged的接口.我们还需要一个表示要使用的行数/列数的属性,这只是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
}
Run Code Online (Sandbox Code Playgroud)


最后,我们可以将它设置为Window中的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>
Run Code Online (Sandbox Code Playgroud)

我要推荐的另一件事是Josh Smith的ContentControl3D实现.因为这可以为你提供你想要在Card类中实现的"翻转"行为.