WPF中的表布局

时间:2009-06-05 00:17:51

标签: wpf

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

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

3 个答案:

答案 0 :(得分:10)

以下是Matt Hamilton建议的使用UniformGrid的示例。

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

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

接下来,我们需要一个包含我们的卡片集合的类,以及一个允许我们设置卡片数量的属性。对于CardCollection,我们可以使用ObservableCollection,因为在添加或删除卡时,它会自动通知UI。 NumberOfCards属性需要它自己的方法来通知UI,为此我们可以implement 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
}


最后,我们可以将它设置为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>

我希望看到的另一件事是Josh Smith的ContentControl3D实现。因为这可以为你提供你想要在Card类中实现的“翻转”行为。

答案 1 :(得分:2)

我建议您为自己的方案UniformGrid。快速搜索产生了this article,其中包含一些可能有用的代码和屏幕截图。

答案 2 :(得分:0)

WPF中有一个表,这是开始使用它的好article。根据经验,WPF中的表并不那么容易使用,使用网格通常是更好的选择。