2010-05-26 5 views
32

Ich erstelle ein WPF-Formular. Eine der Anforderungen ist, dass es ein sektorbasiertes Layout hat, so dass ein Steuerelement explizit in einen der Sektoren/Zellen platziert werden kann.WPF dynamisches Layout mit ItemsControl und Raster

ich ein Tic-Tac-Toe-Beispiel unten geschaffen haben, mein Problem zu vermitteln:

Es gibt zwei Typen und ein Basistyp:

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

Die Datacontext des Formulars auf eine Instanz festgelegt ist von:

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; 
    } 
} 

Und schließlich sieht das XAML wie folgt aus:

<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> 

Was mir beim Start nicht so offensichtlich war, war, dass das ItemsControl-Element jedes Element in einem Container umschließt, sodass meine Grid.Row- und Grid.Column-Bindungen ignoriert werden, da die Bilder nicht direkt im Raster enthalten sind. Daher werden alle Bilder in der Standardzeile und -spalte (0, 0) platziert.

Was geschieht:

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

das gewünschte Ergebnis:

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

Also, meine Frage ist: Wie kann ich die dynamische Platzierung meiner Kontrollen in einem Gitter erreichen ? Ich würde eine XAML/Data Binding/MVVM-freundliche Lösung bevorzugen.

Danke.

Ich habe den letzten Code hier setzen: http://www.centrolutions.com/downloads/TicTacToe.zip

+0

Hey Jason, Jede Chance, den vollen Code Ihres Tic-Tac-Toe zu bekommen? Ich würde gerne einen Blick darauf werfen. Danke! – VitalyB

+2

Leider ist das Projekt nur ein Beispiel und kein voll funktionsfähiges Spiel. Dies war ein Prototyp für ein größeres (Nicht-Tic-Tac-Toe) Projekt. Wenn Sie noch interessiert sind, habe ich einen Link zum endgültigen Code unterhalb der ursprünglichen Frage eingefügt. –

+0

Ich werde es mir ansehen. Vielen Dank! – VitalyB

Antwort

25

Sie auf dem richtigen Weg sind. Sie müssen nur eine Style erstellen und sie auf die ItemsControl.ItemContainerStyle anwenden. Geben Sie dann im Stil einen Setter für die Grid.Row und Grid.Column an. Die ItemContainerStyle wird auf die für jedes Element generierten Container angewendet.

+0

Aha! Ich wusste, dass ich etwas vermisste. Danke für Ihre Hilfe. Das hat super funktioniert. –

+1

Ich versuche das gleiche in Silverlight zu tun, weiß jemand einen Weg, das zu tun? (ItemContainerStyle ist in Silverlight nicht verfügbar ...) –