你仍然必須使用代碼隱藏改變Grid
的RowDefinitions
和ColumnDefinitions
性能在這個例子中,因爲他們不依賴特性。但是所有其餘的邏輯都可以在視圖模型類中處理。
的XAML:
<Window x:Class="GameBoard.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:GameBoard="clr-namespace:GameBoard"
Title="Window1"
SizeToContent="WidthAndHeight">
<Grid Margin="50">
<Grid.Resources>
<!-- This template presents the Piece object. Note that you can't set
the Grid.Row and Grid.Column properties on this Rectangle - well,
you *can*, but the Grid won't see them. See the Style below. -->
<DataTemplate DataType="{x:Type GameBoard:Piece}">
<Rectangle Fill="{Binding Fill}"
Width="50"
Height="50" />
</DataTemplate>
<!-- When the ItemsControl creates its items, it wraps each item in a
ContentPresenter. You have to set Grid.Row and Grid.Column
on this ContentPresenter in order for the Grid to see them. -->
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Grid.Row"
Value="{Binding Row}" />
<Setter Property="Grid.Column"
Value="{Binding Column}" />
</Style>
</Grid.Resources>
<Border BorderBrush="Black"
BorderThickness="1">
<ItemsControl x:Name="Board"
ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Border>
</Grid>
</Window>
的Piece
類 - 很明顯,你需要實現對和Column
性能INotifyPropertyChanged
來處理不斷變化的內容有關。
public class Piece
{
public int Column { get; set; }
public Brush Fill { get; set; }
public int Row { get; set; }
}
填充板:
public Window1()
{
InitializeComponent();
ObservableCollection<Piece> pieces = new ObservableCollection<Piece>();
pieces.Add(
new Piece {Row = 0, Column = 0, Fill = new SolidColorBrush(Colors.BlanchedAlmond)});
pieces.Add(
new Piece {Row = 7, Column = 7, Fill = new SolidColorBrush(Colors.RosyBrown)});
pieces.Add(
new Piece { Row = 3, Column = 4, Fill = new SolidColorBrush(Colors.BlueViolet) });
pieces.Add(
new Piece { Row = 5, Column = 4, Fill = new SolidColorBrush(Colors.Orange) });
Board.DataContext = pieces;
}
我使用的ItemsControl
包含在本例中的碎片。您可以改用ListBox
- 這樣很好,因爲它可以讓您免費選擇物品。請注意,如果您這樣做,則必須將Style
的TargetType
更改爲ListBoxItem
,因爲這是ListBox
包裝其項目元素而不是ContentPresenter
。
編輯:
我前一段寫了這個答案,它有一個問題。
指定Grid.Row
和Grid.Column
屬性使用應用於由網格生成的項目容器的樣式是正確的。找出物品容器是ContentPresenter
,並且爲該類型創建默認樣式不是。 (在這種情況下它可以可靠地工作,但在很多情況下它不會)。
您仍然應該創建一個樣式,但它應該被分配到ItemsControl
的ItemContainerStyle
。此樣式會自動應用於控件爲其項目生成的任何容器元素 - 因此,如果您使用的ItemsControl
是ListBox
,它將應用於ListBoxItem
,如果它是TabControl
,它將應用於TabItem
,等等。
現在我決定在XAML中聲明的列和行的常量號。我實現INotifyPropertyChanged和我幾乎理解你的想法...但如何實現移動件?我認爲我通過鼠標單擊它,然後選擇其他單元格,它應該改變位置(接口實現幫助我改變行和列)。如何找到選定的位置在指定的單元格? – netmajor 2010-04-02 23:42:32
有很多方法可以做到。可能最簡單:創建一個類似Piece類的Cell類,爲每個單元格創建一個Cell類,並在添加Piece對象之前將它們添加到「ItemsSource」。這些棋子在Z順序中比單元格稍後顯示,因此它們將顯示(並通過鼠標點擊來選擇)。如果您使用的是ListBox,SelectedItem將(如果不是null)始終是Piece或Cell。 – 2010-04-03 00:07:24
好的,我明白你的意思了,就像是在空單元格類或Piece之間切換。 但是對於我來說,知道棋子對新位置的實際位置很重要,因爲如果它近距棋子會多倍,其他棋子就會移動。那麼如何從鼠標向下的事件位置(列,行)獲得新的棋子移動?... – netmajor 2010-04-03 00:39:51