Динамическая компоновка WPF с использованием ItemsControl и Grid - PullRequest
35 голосов
/ 26 мая 2010

Я создаю форму WPF. Одним из требований является то, что он имеет макет на основе секторов, чтобы элемент управления можно было явно разместить в одном из секторов / ячеек.

Я создал пример крестики-нолики ниже, чтобы передать мою проблему:

Существует два типа и один базовый тип:

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

DataContext формы устанавливается на экземпляр:

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

И, наконец, XAML выглядит так:

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

Что было не столь очевидно для меня, когда я начал, так это то, что элемент ItemsControl фактически оборачивает каждый элемент в контейнере, поэтому мои привязки Grid.Row и Grid.Column игнорируются, поскольку изображения не содержатся непосредственно в сетке. Таким образом, все изображения помещаются в строку и столбец по умолчанию (0, 0).

Что происходит:

Что происходит http://i48.tinypic.com/29xyl9j.png

Желаемый результат:

Желаемый результат http://i50.tinypic.com/2druhqd.png

Итак, мой вопрос таков: как мне добиться динамического размещения элементов управления в сетке? Я бы предпочел решение для XAML / Data Binding / MVVM.

Спасибо.

Я поставил окончательный код здесь: http://www.centrolutions.com/downloads/TicTacToe.zip

1 Ответ

28 голосов
/ 26 мая 2010

Вы на правильном пути. Вам просто нужно создать Style и применить его к ItemsControl.ItemContainerStyle. Затем в стиле укажите установщик для Grid.Row и Grid.Column. ItemContainerStyle будет применено к контейнерам, сгенерированным для каждого элемента.

...