2010-05-26 13 views
32

Tôi đang tạo biểu mẫu WPF. Một trong những yêu cầu là nó có bố cục dựa trên khu vực để điều khiển có thể được đặt rõ ràng trong một trong các lĩnh vực/ô.Bố cục động WPF với ItemsControl và Grid

Tôi đã tạo ra một ví dụ tic-tac-toe dưới đây để truyền đạt vấn đề của tôi:

Có hai loại và một loại cơ sở:

public class XMoveViewModel : MoveViewModel 
{ 
} 
public class OMoveViewModel : MoveViewModel 
{ 
} 
public class MoveViewModel 
{ 
    public int Row { get; set; } 
    public int Column { get; set; } 
} 

Các DataContext của mẫu được thiết lập để một thể hiện của:

public class MainViewModel : ViewModelBase 
{ 
    public MainViewModel() 
    { 
     Moves = new ObservableCollection<MoveViewModel>() 
     { 
      new XMoveViewModel() { Row = 0, Column = 0 }, 
      new OMoveViewModel() { Row = 1, Column = 0 }, 
      new XMoveViewModel() { Row = 1, Column = 1 }, 
      new OMoveViewModel() { Row = 0, Column = 2 }, 
      new XMoveViewModel() { Row = 2, Column = 2} 
     }; 
    } 
    public ObservableCollection<MoveViewModel> Moves 
    { 
     get; 
     set; 
    } 
} 

Và cuối cùng, XAML trông như thế này:

<Window.Resources> 
    <DataTemplate DataType="{x:Type vm:XMoveViewModel}"> 
     <Image Source="XMove.png" Grid.Row="{Binding Path=Row}" Grid.Column="{Binding Path=Column}" Stretch="None" /> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type vm:OMoveViewModel}"> 
     <Image Source="OMove.png" Grid.Row="{Binding Path=Row}" Grid.Column="{Binding Path=Column}" Stretch="None" /> 
    </DataTemplate> 
</Window.Resources> 
<Grid> 
    <ItemsControl ItemsSource="{Binding Path=Moves}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <Grid ShowGridLines="True"> 
        <Grid.RowDefinitions> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
        </Grid.RowDefinitions> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
        </Grid.ColumnDefinitions> 
       </Grid> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
    </ItemsControl> 
</Grid> 

Điều không rõ ràng đối với tôi khi tôi bắt đầu là phần tử ItemsControl thực sự bao bọc từng mục trong một vùng chứa, vì vậy các kết buộc Grid.Row và Grid.Column của tôi bị bỏ qua vì các hình ảnh không được chứa trực tiếp trong lưới. Vì vậy, tất cả các hình ảnh được đặt trong hàng và cột mặc định (0, 0).

gì đang xảy ra:

What is happening http://i48.tinypic.com/29xyl9j.png

Kết quả mong muốn:

The desired result http://i50.tinypic.com/2druhqd.png

Vì vậy, câu hỏi của tôi là thế này: làm thế nào tôi có thể đạt được vị trí năng động của kiểm soát của tôi trong một mạng lưới ? Tôi thích một giải pháp XAML/Data Binding/MVVM-friendly.

Cảm ơn.

Tôi đã đặt mã thức ở đây: http://www.centrolutions.com/downloads/TicTacToe.zip

+0

Xin chào Jason, Có cơ hội nhận mã đầy đủ của tic-tac-toe của bạn không? Tôi rất muốn có một cái nhìn. Cảm ơn! – VitalyB

+2

Thật không may, dự án chỉ là một ví dụ và không phải là một trò chơi đầy đủ chức năng. Đây là một nguyên mẫu cho một dự án lớn hơn (không tic-tac-toe). Nếu bạn vẫn quan tâm, tôi đã đặt một liên kết tới mã cuối cùng bên dưới câu hỏi ban đầu. –

+0

Tôi sẽ cho nó một cái nhìn. Cảm ơn! – VitalyB

Trả lời

25

Bạn đang đi đúng hướng. Bạn chỉ cần tạo một Style và áp dụng nó cho ItemsControl.ItemContainerStyle. Sau đó, trong phong cách, hãy chỉ định trình thiết lập cho Grid.RowGrid.Column. ItemContainerStyle sẽ được áp dụng cho các vùng chứa được tạo cho từng mục.

+0

Aha! Tôi biết tôi đã thiếu một cái gì đó. Cảm ơn sự giúp đỡ của bạn. Điều đó làm việc tuyệt vời. –

+1

Tôi đang cố gắng làm điều tương tự trong Silverlight, có ai biết cách để làm điều đó không? (ItemContainerStyle không khả dụng trong Silverlight ...) –