2009-03-19 11 views
4

Ich habe eine UserControl, die ich verwende, um eine Liste von UIElement s anzuzeigen. Die Steuerung besteht aus einem einzigen ItemsControl mit seiner ItemPanelTemplate für eine horizontale StackPanel geschaltet, dessen ItemsSource gebunden an eine durch das UserControlItemTemplate und dessen Satz in der UserControl.ResourcesDependencyProperty ausgesetzt.WPF - ItemTemplate reagiert nicht wie erwartet

Alles funktioniert gut, außer die ItemTemplate nie bekommen, und ich kann nicht sehen, warum. Die vollständige Quelle ist unten.

UserControl.xaml -

<UserControl x:Name="UC" x:FieldModifier="private" x:Class="ContentSliderControl.ContentSlider" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
<UserControl.Resources> 

    <DataTemplate x:Key="pageTemplate"> 
     <Border CornerRadius="10" Padding="5" Height="200" Width="200" Background="#333"> 
      <ContentControl Content="{Binding}"/> 
     </Border> 
    </DataTemplate> 

    <ItemsPanelTemplate x:Key="template"> 
     <StackPanel IsItemsHost="True" 
      Orientation="Horizontal" 
      ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
      ScrollViewer.VerticalScrollBarVisibility="Disabled"/> 
    </ItemsPanelTemplate> 
</UserControl.Resources> 

<ItemsControl ItemsPanel="{StaticResource template}" 
       ItemTemplate="{StaticResource pageTemplate}" 
       ItemsSource="{Binding ElementName=UC,Path=Pages}"/> 

UserControl.xaml.cs -

[ContentProperty("Pages")] 
public partial class ContentSlider : UserControl 
{ 


    public List<UIElement> Pages 
    { 
     get { return (List<UIElement>)GetValue(PagesProperty); } 
     //set { SetValue(PagesProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for Pages. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty PagesProperty = 
     DependencyProperty.Register("Pages", typeof(List<UIElement>), typeof(ContentSlider), new UIPropertyMetadata(null)); 



    public ContentSlider() 
    { 
     InitializeComponent(); 
    } 
} 

}

ich verbrauchen die Kontrolle in meinem Hauptfenster so -

<slider:ContentSlider > 
    <slider:ContentSlider.Pages> 
     <Button>1</Button> 
     <Button>2</Button> 
     <Button>3</Button> 
     <Button>4</Button> 
    </slider:ContentSlider.Pages> 
</slider:ContentSlider> 

Die Schaltflächen erscheinen gut, aber nicht innerhalb des 200-Pixel-Quadrats.

Jede Hilfe wäre sehr geschätzt. Danke.

Antwort

4

Es ist, weil es eine Liste von UIElement ist, die Elementvorlage wird nur angewendet, wenn die Elemente nicht direkt angezeigt werden können.

+0

Was würden Sie dann vorschlagen? – Stimul8d

+0

Auch, wenn ich die ItemsControl für eine Listbox vertauschen, dann rendern sie wie erwartet, also bin ich mir nicht sicher, dass Sie genau dort sind – Stimul8d

+0

Scheint muss ich meine Worte essen! Danke Nir. – Stimul8d

6

Nir ist korrekt, ItemsControl fügt Artikel direkt zu seinem Panel hinzu, wenn sie UIElements sind. Ich konnte keine Erwähnung dieses Verhaltens in MSDN finden, aber Dr. WPF erwähnt es in his article on item containers:

Wenn ein UIElement auf die Items-Auflistung einer expliziten Item Instanz hinzugefügt wird (im Gegensatz zu einer Instanz von einem gegen abgeleitete Klasse wie ListBox), wird es ein direktes Kind des Elementbedienfelds. Wenn ein Nicht-UIElement hinzugefügt wird, wird es in einen ContentPresenter eingebunden.

Ihre Lösung ist wahrscheinlich eine ListBox stattdessen zu verwenden, und legen Sie ItemContainerStyle auf einen neuen Style für ListBoxItem, und in diesem Stil, eine ControlTemplate mit Ihrem Border in sie verwenden.

+0

Gut ist das nicht irgendein verrücktes Verhalten. Danke dafür Robert, ich gebe Nir dann die richtige Antwort und wähle dich ab. Schade, du kannst nicht mehr als eine richtige Antwort haben, oder? – Stimul8d

-1

Wenn Sie die Eigenschaft DataType auf DataTemplate festlegen, würde es funktionieren.

4

Nir ist richtig, dieser Brauch Items Implementierung, das Problem zu lösen und lassen Sie Ihre eigene ItemTemplate verwenden:

public class ItemsControlForUIElement : ItemsControl 
{ 
    protected override DependencyObject GetContainerForItemOverride() 
    { 
     return new ContentPresenter(); 
    } 
    protected override bool IsItemItsOwnContainerOverride(object item) 
    { 
     return false; 
    } 
} 
2

Robert Macnee den Grund auf den Kopf genagelt. Seine Lösung beinhaltet die Verwendung der Kontrollschablone, die für ein gegebenes Szenario möglicherweise übertrieben ist. Alternativ können Sie einen ListBox - stellen Sie die ItemContainerStyle auf einen neuen Stil für ListBoxItem, und in diesem Stil, stellen Sie die ContentTemplate auf die DataTemplate, die Sie im ListBoxItemTemplate verwenden wollte.