2010-09-28 2 views
2

Просто, чтобы дать вам быстрый обзор, просто пытаясь создать редактор фрагментов. Поэтому я создал объекты пользовательской черепицы, которые будут отображаться с помощью шаблона contenttemplate, отображающего каждый как прямоугольник. Я использую listbox как мой контейнер, но я установил ItemPanelTemplate этого контейнера для использования сетки. Проблема в том, что Grid.Row или Grid.Column в моем contenttemplate ничего не делает. Я уверен, что это связано с тем, что моя сетка определена внутри шаблона, но я не уверен, как это сделать.Пользовательский контроль не перемещается к правильному расположению сетки

Вот мой 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> 

ответ

2

Причина заключается в том, что Grid.Row и Grid.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}"/> 

Здесь , и Column должны быть общедоступными свойствами элементов 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; } 
} 
+0

Позвольте мне расширить одну вещь. Было бы лучше, если бы я настроил contenttemplate элемента listbox с contentproperty и в том contentproperty, который я бы тогда поставил мой объект для черепицы? Надеюсь, это разъяснит, о чем я пытался раньше. – Ilya

+0

Еще одна вещь. Когда я создал шаблон contenttemplate, я сделал шаблон, заменив каждый ListboxItem на объект плитки и прямоугольник внутри. У меня нет свойства Content в шаблоне, так почему здесь работает Content.Row? Это не похоже на то, что я поместил плитку в свойство контента ... сам элемент является плиткой. Итак, разве это не просто «строка», а не «Content.Row»? – Ilya

+0

См. Мои правки выше. – 2010-09-28 08:39:27

Смежные вопросы