开发者

Custom control not moving to correct grid location

Just to give you a quick overview, just trying to create somewhat of a tile editor. So I made custom tile objects which will be represted through a contenttemplate displaying each as a rectangle. I am using a listbox as my container but I set the ItemsPanelTemplate of that container to use a grid. The problem is, setting Grid.Row or Grid.Column in my contenttemplate does nothing. I'm sure it has something to do with the fact that my grid is defined within the template but I'm not sure how.

Here is my 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开发者_JS百科:Tile></local:Tile> 
</ListBox>  


The reason is that Grid.Row and Grid.Column only have effect on the direct children of the Grid control. The children of your Grid, however, are not the Tile controls, but the ListBoxItem controls that are created implicitly. Therefore, you must set the position like this:

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

You also can do it like this in the ItemContainerStyle:

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

You even can use data binding:

<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}"/> 

Here, Row and Column must be public properties of the ListBox items.

Here is a complete example to make it clear:

Custom control not moving to correct grid location

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

The Tile class is defined as follows:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜