Вот пример с ним, используя UniformGrid, как предположил Мэтт Гамильтон.
Во-первых, давайте создадим классы и данные, которые мы будем использовать. Каждая карта будет представлена объектом карты, и имеет свойство лица:
public class Card
{
public string Face { get; set; }
public Card() { }
}
Далее, нам потребуются класс, который имеет нашу коллекцию карт, а также свойство, которое позволяет нам установить количество карт , Для CardCollection мы можем использовать ObservableCollection, так как автоматически будет уведомлять пользовательский интерфейс при добавлении или удалении Карты. Свойству NumberOfCards потребуется собственный метод для уведомления пользовательского интерфейса, для этого мы можем использовать 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
}
Наконец, мы можем установить это как наши DataContext в окне , и привязать к нашему классу карт в XAML. Для 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 реализация Джоша Смита. Так как это может дать вам «перевернутое» поведение, которое вы ищете для реализации в классе карты довольно хорошо.
Очень приятно! +1 ... надеюсь, что это «принято»! –
О, это потрясающе, спасибо вам большое! –