自定义控件无法移动到正确的网格位置

时间:2010-09-28 05:12:00

标签: wpf

只是为了快速概述一下,只是尝试创建一些tile编辑器。所以我制作了自定义的瓷砖对象,这些对象将通过内容模板重新显示,每个模板显示为矩形。我使用列表框作为我的容器,但我将该容器的ItemsPanelTemplate设置为使用网格。问题是,在我的contenttemplate中设置Grid.Row或Grid.Column什么都不做。我确定它与我的网格在模板中定义的事实有关,但我不确定如何。

这是我的XAML:

<Window x:Class="InvisTile.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:CustomControls"
    Title="MainWindow" Height="200" Width="200">

<Window.Resources>
    <ControlTemplate x:Key="TileTemplate" TargetType="{x:Type ListBoxItem}">

        //Hard coded to grid location but only staying in 0,0
        <local:Tile BorderBrush="Aqua" MouseDown="Tile_MouseDoubleClick" Grid.Row="1" Grid.Column="1">
            <Rectangle Fill="Transparent" Stroke="Green"></Rectangle>
        </local:Tile>
    </ControlTemplate>
</Window.Resources>
<ListBox Name="lstTiles">
    <ListBox.ItemContainerStyle>
        <Style>
            <Setter Property="Control.Template" Value="{StaticResource TileTemplate}" />
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid ShowGridLines="True">
                <Grid.RowDefinitions>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>
            </Grid>
        </ItemsPanelTemplate>          
    </ListBox.ItemsPanel>     
   <local:Tile></local:Tile> 
</ListBox>  

1 个答案:

答案 0 :(得分:2)

原因是Grid.RowGrid.Column仅对Grid控件的直接子项产生影响。但是,Grid的子项不是Tile控件,而是隐式创建的ListBoxItem控件。因此,您必须设置如下位置:

ListBoxItem li = new ListBoxItem();
li.Content = "item1";
Grid.SetColumn(li, 1);
Grid.SetRow(li, 1);
lstTiles.Items.Add(li);

您也可以在ItemContainerStyle中执行此操作:

<Setter Property="Grid.Row" Value="1"/>
<Setter Property="Grid.Column" Value="1"/> 

您甚至可以使用数据绑定:

<Setter Property="Grid.Row" Value="{Binding RelativeSource={x:Static RelativeSource.Self},
    Path=Content.Row}"/>
<Setter Property="Grid.Column" Value="{Binding RelativeSource={x:Static RelativeSource.Self},
    Path=Content.Column}"/> 

此处,RowColumn必须是ListBox项的公共属性。

以下是一个完整的示例:

Screenshot

<Window x:Class="InvisTile.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:InvisTile"
    Title="Window1" Height="200" Width="200">

    <Window.Resources>
        <ControlTemplate x:Key="TileTemplate" TargetType="{x:Type ListBoxItem}">
            <Border BorderThickness="1" BorderBrush="Aqua" Background="LightGray" Margin="4">
                <Grid  VerticalAlignment="Center" HorizontalAlignment="Center">
                    <ContentPresenter/>
                </Grid>
            </Border>
        </ControlTemplate>
    </Window.Resources>
    <ListBox Name="lstTiles">
        <ListBox.ItemContainerStyle>
            <Style>
                <Setter Property="Control.Template" Value="{StaticResource TileTemplate}" />
                <Setter Property="Grid.Row" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, 
    Path=Content.Row}"/>
                <Setter Property="Grid.Column" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, 
    Path=Content.Column}"/>
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid ShowGridLines="True">
                    <Grid.RowDefinitions>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                </Grid>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.Items>
            <local:Tile Text="(0,0)" Row="0" Column="0"/>
            <local:Tile Text="(0,1)" Row="0" Column="1"/>
            <local:Tile Text="(1,0)" Row="1" Column="0"/>
            <local:Tile Text="(1,1)" Row="1" Column="1"/>
        </ListBox.Items>
    </ListBox>
</Window>

Tile类的定义如下:

public class Tile
{
    public Tile() {}
    public string Text { get; set; }
    public int Row { get; set; }
    public int Column { get; set; }
    public override string ToString() { return Text; }
}