我正致力于制作纸牌游戏" Memory"在WPF中。我在UI方面遇到了麻烦。我已经设置好了,当用户选择难度时,它会动态设置卡座的大小(4x4很容易,这就是我们将要工作/谈论的概念证明)。在选择不同的困难时,如何允许动态更改网格?
这是您设置难度的地方(所有卡片都用于测试目的..)
private void SetDifficulty(Difficulty difficulty) {
//Clearing CardList
CardList.Clear();
//Switching on the diff
switch (difficulty) {
case Difficulty.Easy:
CardList = new ObservableCollection<Card>{
new Card {
Image = Resources.Bowser
},
new Card(),
new Card(),
new Card(),
new Card(),
new Card(),
new Card(),
new Card(),
new Card(),
new Card(),
new Card(),
new Card(),
new Card(),
new Card(),
new Card(),
new Card()
};
break;
case Difficulty.Medium:
break;
case Difficulty.Hard:
break;
default:
throw new ArgumentOutOfRangeException(nameof(difficulty), difficulty, null);
}
}
XAML:
<Window x:Class="MemoryGame.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MemoryGame.Views"
xmlns:viewModels="clr-namespace:MemoryGame.ViewModels"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance viewModels:MemoryGameViewModel}"
Title="MainView" Height="300" Width="300">
<Grid ShowGridLines="True">
<ListBox ItemsSource="{Binding Path=CardList}">
<ListBox.ItemTemplate>
<DataTemplate DataType="viewModels:Card">
<StackPanel Orientation="Horizontal" Width="50" Height="50" >
<!--<Image Source="/Pictures/Luigi.jpg"></Image>-->
<Button Content="{Binding Image, UpdateSourceTrigger=PropertyChanged}" Margin="5" Height="50" Width="50">
</Button>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
答案 0 :(得分:1)
我更希望在ItemsControl
上使用ListBox
来获取XAML中的集合。我还要绑定集合的宽度并添加允许包装对象的包装器面板:
<ItemsControl ItemsSource="{Binding Path=CardList} Width="{Binding CollWidth}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="viewModels:Card">
<StackPanel Orientation="Horizontal" Width="50" Height="50" >
<!--<Image Source="/Pictures/Luigi.jpg"></Image>-->
<Button Content="{Binding Image, UpdateSourceTrigger=PropertyChanged}" Margin="5" Height="50" Width="50">
</Button>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<!-- A WrapPanel ensures the items wrap to the next line -->
<!-- when it runs out of room in the collection dimensions -->
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
不要忘记添加CollWidth
属性:
private int _collWidth;
public int CollWidth {
get { return _collWidth; }
set {
_collWidth = value;
OnPropertyChanged("CollWidth");
}
}
现在您可以轻松修改SetDificulty
方法:
private void SetDifficulty(Difficulty difficulty) {
// this auto clears everything
CardList = new ObservableCollection<Card>();
//Switching on the diff
switch (difficulty) {
case Difficulty.Easy:
// set the width in each level of difficulty to allow wrapper to make nice looking grid
CollWidth = 200; // (button width is 50) * 4 buttons = 200
for(int i=0;i<16;i++)
CardList.Add(new Card()); // or whatever constructor
break;
case Difficulty.Medium:
CollWidth = 250; // (button width is 50) * 5 buttons = 250
for(int i=0;i<25;i++)
CardList.Add(new Card()); // or whatever constructor
break;
case Difficulty.Hard:
CollWidth = 300; // (button width is 50) * 6 buttons = 300
for(int i=0;i<36;i++)
CardList.Add(new Card()); // or whatever constructor
break;
default:
throw new ArgumentOutOfRangeException(nameof(difficulty), difficulty, null);
}
}
您不必担心该集合的Height
。添加的<WrapPanel>
会为您处理。您只需指定CollWidth
,并且换页面板会在每行中放置CollWidth
/ 50
个按钮
答案 1 :(得分:0)
您可以使用UniformGrid
作为ListBox的ItemsPanel,并将其Columns
或Rows
属性绑定到视图模型中的属性:
<ListBox ItemsSource="{Binding CardList}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="{Binding GridSize}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Image}" Margin="5" Height="50" Width="50"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
注意,在Button的Content Binding上设置UpdateSourceTrigger=PropertyChanged
是没有意义的。它只会对实际触发源属性更新的Bindings产生影响,即TwoWay或OneWayToSource Bindings。
在后面的代码中创建UI元素也是不好的做法,例如Image
类的Card
属性。更好地声明类型为ImageSource
的属性,并在XAML中绑定Image控件的Source
属性:
public class Card
{
public ImageSource Image { get; set; }
...
}
...
var card = new Card
{
Image = new BitmapeImage(new Uri("pack://application:,,,/Picures/Luigi.jpg"))
};
XAML:
<ListBox.ItemTemplate>
<DataTemplate>
<Button Margin="5" Height="50" Width="50">
<Image Source="{Binding Image}"/>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>