Compartilhar via


Visão geral de Controles de Modelos de Conteúdo

Este tópico aborda os modelos de conteúdo usados por classes que herdam de Control. O modelo de conteúdo especifica os tipos de objetos que um controle pode conter. Neste tópico, o termo "Controle" está limitado a uma classe que tem a classe Control em algum lugar na sua hierarquia de classe. Os quatro modelos de conteúdo abordados neste tópico são definidos pelas quatro classes que herdam de Control:

Esses quatro classes atuar sistema autônomo classes base para a maioria dos controles da WPF. Classes que usam esses modelos de conteúdo podem conter sistema autônomo mesmos tipos de conteúdo e tratar o conteúdo da mesma forma; qualquer tipo de objeto que pode ser colocado em um ContentControl (ou uma classe que herda de ContentControl) podem ser colocados em um controle que tenha qualquer um dos outros três modelos conteúdos. A figura a seguir mostra um controle de cada modelo de conteúdo que contém uma imagem e texto.

Button, GroupBox, Listbax, TreeViewItem

Este tópico contém as seguintes seções.

  • Pré-requisitos
  • ContentControl
  • HeaderedContentControl
  • ItemsControl
  • HeaderedItemsControl
  • Tópicos relacionados

Pré-requisitos

Este tópico pressupõe que você tem uma noção básica dos WPF e sabe como adicionar controles a um aplicativo. Para obter mais informações, consulte Getting Started with Windows Presentation Foundation e Visão geral sobre controles.

ContentControl

O modelo de conteúdo mais simples dos quatro é o ContentControl, que tem uma propriedade Content. A propriedade Content é do tipo Object, portanto, há há restrições sobre o que você pode colocar em um ContentControl. Você pode usar Extensible Application Markup Language (XAML) ou código para definir o Content.

Os seguintes controles usam o modelo de conteúdo ContentControl:

O exemplo a seguir demonstra como criar quatro controles Button com Content definido como um dos seguitnes:

ObservaçãoObservação:

O exemplo Extensible Application Markup Language (XAML) versão poderia usar o <Button.Content> Rótulos em torno do conteúdo de cada botão, mas não é necessário. Para obter mais informações, consulte XAML Overview.

<!--Create a Button with a string as its content.-->
<Button>This is string content of a Button</Button>

<!--Create a Button with a DateTime object as its content.-->
<Button xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <sys:DateTime>2004/3/4 13:6:55</sys:DateTime>
</Button>

<!--Create a Button with a single UIElement as its content.-->
<Button>
  <Rectangle Height="40" Width="40" Fill="Blue"/>
</Button>

<!--Create a Button with a panel that contains multiple objects 
as its content.-->
<Button>
  <StackPanel>
    <Ellipse Height="40" Width="40" Fill="Blue"/>
    <TextBlock TextAlignment="Center">Button</TextBlock>
  </StackPanel>
</Button>
' Add a string to a button.
Dim stringContent As New Button()
stringContent.Content = "This is string content of a Button"

' Add a DateTime object to a button.
Dim objectContent As New Button()
Dim dateTime1 As New DateTime(2004, 3, 4, 13, 6, 55)

objectContent.Content = dateTime1

' Add a single UIElement to a button.
Dim uiElementContent As New Button()

Dim rect1 As New Rectangle()
rect1.Width = 40
rect1.Height = 40
rect1.Fill = Brushes.Blue
uiElementContent.Content = rect1

' Add a panel that contains multpile objects to a button.
Dim panelContent As New Button()
Dim stackPanel1 As New StackPanel()
Dim ellipse1 As New Ellipse()
Dim textBlock1 As New TextBlock()

ellipse1.Width = 40
ellipse1.Height = 40
ellipse1.Fill = Brushes.Blue

textBlock1.TextAlignment = TextAlignment.Center
textBlock1.Text = "Button"

stackPanel1.Children.Add(ellipse1)
stackPanel1.Children.Add(textBlock1)

panelContent.Content = stackPanel1
// Create a Button with a string as its content.
Button stringContent = new Button();
stringContent.Content = "This is string content of a Button";

// Create a Button with a DateTime object as its content.
Button objectContent = new Button();
DateTime dateTime1 = new DateTime(2004, 3, 4, 13, 6, 55);

objectContent.Content = dateTime1;

// Create a Button with a single UIElement as its content.
Button uiElementContent = new Button();

Rectangle rect1 = new Rectangle();
rect1.Width = 40;
rect1.Height = 40;
rect1.Fill = Brushes.Blue;
uiElementContent.Content = rect1;

// Create a Button with a panel that contains multiple objects 
// as its content.
Button panelContent = new Button();
StackPanel stackPanel1 = new StackPanel();
Ellipse ellipse1 = new Ellipse();
TextBlock textBlock1 = new TextBlock();

ellipse1.Width = 40;
ellipse1.Height = 40;
ellipse1.Fill = Brushes.Blue;

textBlock1.TextAlignment = TextAlignment.Center;
textBlock1.Text = "Button";

stackPanel1.Children.Add(ellipse1);
stackPanel1.Children.Add(textBlock1);

panelContent.Content = stackPanel1;

A figura a seguir mostra os quatro botões criados no exemplo anterior.

Quatro botões

HeaderedContentControl

The HeaderedContentControl herda o Content propriedade a partir de ContentControl e define o Header propriedade do tipo Object. Header Fornece um título para o controle. Como a Content propriedade de um ContentControl, o Header pode ser qualquer tipo. WPF três controles que herdam fornecido HeaderedContentControl:

O exemplo a seguir cria um TabControl (uma ItemsControl) que contém dois objetos TabItem. O primeiro TabItem tem conteúdo rico em ambos os Header e o Content: the Header é conjunto para um StackPanel que contém um Ellipse e um TextBlocke o Content é conjunto para um StackPanel que contém um TextBlock e um Label. O Header do segundo TabItem é definido como uma sequência de caracteres, e o Content é definido para um único TextBlock.

<TabControl>
  <TabItem>
    <TabItem.Header>
      <StackPanel Orientation="Horizontal">
        <Ellipse Width="10" Height="10" Fill="DarkGray"/>
        <TextBlock>Tab 1</TextBlock>
      </StackPanel>
    </TabItem.Header>
    <StackPanel>
      <TextBlock>Enter some text</TextBlock>
      <TextBox Name="textBox1" Width="50"/>
    </StackPanel>
  </TabItem>
  <TabItem Header="Tab 2">
    <!--Bind TextBlock.Text to the TextBox on the first
    TabItem.-->
    <TextBlock Text="{Binding ElementName=textBox1, Path=Text}"/>
  </TabItem>
</TabControl>

A ilustração a seguir mostra a TabControl criado por esse exemplo.

TabControl

ItemsControl

Os controles que herdam de ItemsControl contem uma coleção de objetos. Um exemplo de um ItemsControl é ListBox. Você pode usar tanto a propriedade ItemsSource quanto a propriedade Items para preencher um ItemsControl.

Propriedade ItemsSource

The ItemsSource propriedade das ItemsControl permite que você use qualquer tipo que implemente IEnumerable sistema autônomo o conteúdo da ItemsControl. ItemsSource costuma ser utilizada para exibir um conjunto de dados ou BIND um ItemsControl como um objeto da coleção.

O exemplo a seguir cria uma classe chamada MyData que é uma simples coleção de sequência de caracteres.

Public Class MyData
    Inherits ObservableCollection(Of String)

    Public Sub New()  '

        Add("Item 1")
        Add("Item 2")
        Add("Item 3")

    End Sub 'New
End Class 'MyData
public class MyData : ObservableCollection<string>
{
    public MyData()
    {
        Add("Item 1");
        Add("Item 2");
        Add("Item 3");
    }
}

O exemplo a seguir vincula ItemsSource a MyData.

<!--Create an instance of MyData as a resource.-->
<src:MyData x:Key="dataList"/>


...


<ListBox ItemsSource="{Binding Source={StaticResource dataList}}"/>
Dim listBox1 As New ListBox()
Dim listData As New MyData()
Dim binding1 As New Binding()

binding1.Source = listData
listBox1.SetBinding(ListBox.ItemsSourceProperty, binding1)
ListBox listBox1 = new ListBox();
MyData listData = new MyData();
Binding binding1 = new Binding();

binding1.Source = listData;
listBox1.SetBinding(ListBox.ItemsSourceProperty, binding1);

A figura a seguir mostra a ListBox criada no exemplo anterior.

ListBox

Para obter mais informações, consulte Revisão de Associação de Dados.

Propriedade Items

Se você não desejar usar um objeto que implementa IEnumerable para preencher a ItemsControl, você pode adicionar itens usando a propriedade Items. Os itens em um ItemsControl podem ter tipos que são diferentes uns dos outros. Por exemplo, um ListBox pode conter um item que é uma sequência de caracteres e outro item que é um Image.

ObservaçãoObservação:

Quando o ItemsSource propriedade for definida, você pode usar o Items propriedade para ler o ItemCollection, mas não é possível adicionar ou modificar o ItemCollection. A configuração da propriedade ItemsSource como uma referência nula (Nothing no Visual Basic) remove a coleção e restaura uso para Items, que será uma ItemCollection vazia.

O exemplo a seguir cria um ListBox com quatro tipos diferentes de itens.

<!--Create a ListBox that contains a string, a Rectangle,
     a Panel, and a DateTime object. These items can be accessed
     via the Items property.-->
<ListBox xmlns:sys="clr-namespace:System;assembly=mscorlib"
         Name="simpleListBox">

  <!-- The <ListBox.Items> element is implicitly used.-->
  This is a string in a ListBox

  <sys:DateTime>2004/3/4 13:6:55</sys:DateTime>

  <Rectangle Height="40" Width="40"  Fill="Blue"/>

  <StackPanel Name="itemToSelect">
    <Ellipse Height="40" Fill="Blue"/>
    <TextBlock>Text below an Ellipse</TextBlock>
  </StackPanel>

  <TextBlock>String in a TextBlock</TextBlock>
  <!--</ListBox.Items>-->
</ListBox>
' Create a Button with a string as its content.
listBox1.Items.Add("This is a string in a ListBox")

' Create a Button with a DateTime object as its content.
Dim dateTime1 As New DateTime(2004, 3, 4, 13, 6, 55)

listBox1.Items.Add(dateTime1)

' Create a Button with a single UIElement as its content.
Dim rect1 As New Rectangle()
rect1.Width = 40
rect1.Height = 40
rect1.Fill = Brushes.Blue
listBox1.Items.Add(rect1)

' Create a Button with a panel that contains multiple objects 
' as its content.
Dim ellipse1 As New Ellipse()
Dim textBlock1 As New TextBlock()

ellipse1.Width = 40
ellipse1.Height = 40
ellipse1.Fill = Brushes.Blue

textBlock1.TextAlignment = TextAlignment.Center
textBlock1.Text = "Text below an Ellipse"

stackPanel1.Children.Add(ellipse1)
stackPanel1.Children.Add(textBlock1)

listBox1.Items.Add(stackPanel1)
// Add a String to the ListBox.
listBox1.Items.Add("This is a string in a ListBox");

// Add a DateTime object to a ListBox.
DateTime dateTime1 = new DateTime(2004, 3, 4, 13, 6, 55);

listBox1.Items.Add(dateTime1);

// Add a Rectangle to the ListBox.
Rectangle rect1 = new Rectangle();
rect1.Width = 40;
rect1.Height = 40;
rect1.Fill = Brushes.Blue;
listBox1.Items.Add(rect1);

// Add a panel that contains multpile objects to the ListBox.
Ellipse ellipse1 = new Ellipse();
TextBlock textBlock1 = new TextBlock();

ellipse1.Width = 40;
ellipse1.Height = 40;
ellipse1.Fill = Brushes.Blue;

textBlock1.TextAlignment = TextAlignment.Center;
textBlock1.Text = "Text below an Ellipse";

stackPanel1.Children.Add(ellipse1);
stackPanel1.Children.Add(textBlock1);

listBox1.Items.Add(stackPanel1);

A figura a seguir mostra a ListBox criada no exemplo anterior.

ListBox com quatro tipos de conteúdo

Classes Item Container

Cada ItemsControl que vem com WPF tem uma classe correspondente que representa um item no ItemsControl. A tabela a seguir lista os objetos ItemsControl que vêm com WPF e seus Item Containers correspondentes.

ItemsControl

Item container

ComboBox

ComboBoxItem

ContextMenu

MenuItem

ListBox

ListBoxItem

ListView

ListViewItem

Menu

MenuItem

StatusBar

StatusBarItem

TabControl

TabItem

TreeView

TreeViewItem

Você pode criar explicitamente um contêiner de itens para cada item no ItemsControl, mas isso não é necessário. Criar ou não um contêiner de itens no seu ItemsControl depende muito da situação. Por exemplo, se você vincular dados propriedade ItemsSource, você não criará explicitamente um contêiner de itens. Os pontos a seguir são importantes para ter em mente:

  • O tipo de objetos no ItemCollection varia dependendo se você cria um contêiner de itens explicitamente.

  • Você poderá obter o contêiner de itens mesmo se não criá-lo explicitamente.

  • Um Style com o TargetType definido como um contêiner de itens é aplicado independentemente de o contêiner de itens ser explicitamente criado.

  • A herança de propriedades se comporta de forma diferente para contêiners de itens implicitamente e explicitamente criados porque somente contêiners de itens criados explicitamente fazem parte da árvore lógica.

Para ilustrar esses pontos, o exemplo a seguir cria dois controles ListBox. O exemplo cria objetos ListBoxItem para o primeiro ListBox, mas não para a segunda ListBox. No segundo caso, um ListBoxItem é implicitamente criada para cada item em ListBox.

<!--Explicitly create a ListBoxItem for each item in the ListBox-->
<ListBox xmlns:sys="clr-namespace:System;assembly=mscorlib"
         Name="listBoxItemListBox">
  <!-- The <ListBox.Items> element is implicitly used.-->
  <ListBoxItem>
    This is a string in a ListBox
  </ListBoxItem>
  <ListBoxItem>
    <sys:DateTime>2004/3/4 13:6:55</sys:DateTime>
  </ListBoxItem>
  <ListBoxItem>
    <Rectangle Height="40" Width="40" Fill="Blue"/>
  </ListBoxItem>
  <ListBoxItem>
    <StackPanel>
      <Ellipse Height="40" Width="40" Fill="Blue"/>
      <TextBlock>Text below an Ellipse</TextBlock>
    </StackPanel>
  </ListBoxItem>
  <!--</ListBox.Items>-->
</ListBox>


...


<!--Create a ListBox that contains a string, a Rectangle,
     a Panel, and a DateTime object. These items can be accessed
     via the Items property.-->
<ListBox xmlns:sys="clr-namespace:System;assembly=mscorlib"
         Name="simpleListBox">

  <!-- The <ListBox.Items> element is implicitly used.-->
  This is a string in a ListBox

  <sys:DateTime>2004/3/4 13:6:55</sys:DateTime>

  <Rectangle Height="40" Width="40"  Fill="Blue"/>

  <StackPanel Name="itemToSelect">
    <Ellipse Height="40" Fill="Blue"/>
    <TextBlock>Text below an Ellipse</TextBlock>
  </StackPanel>

  <TextBlock>String in a TextBlock</TextBlock>
  <!--</ListBox.Items>-->
</ListBox>

O ItemCollection para cada ListBox é diferente. Cada item na propriedade Items do primeiro ListBox é um ListBoxItem, mas é um tipo diferente no segundo ListBox. O exemplo a seguir confirma isso iterando pelos itens em ambos controles ListBox e verificando o tipo de cada item.

    Console.WriteLine("Items in simpleListBox:")

    For Each item As Object In simpleListBox.Items
        Console.WriteLine(item.GetType().ToString())
    Next item

    Console.WriteLine(vbCr + "Items in listBoxItemListBox:")

    For Each item As Object In listBoxItemListBox.Items
        Console.WriteLine(item.GetType().ToString())
    Next item

End Sub 'ReportLBIs


...


'
'        Items in simpleListBox:
'        System.String
'        System.Windows.Shapes.Rectangle
'        System.Windows.Controls.StackPanel
'        System.DateTime
'
'        Items in listBoxItemListBox:
'        System.Windows.Controls.ListBoxItem
'        System.Windows.Controls.ListBoxItem
'        System.Windows.Controls.ListBoxItem
'        System.Windows.Controls.ListBoxItem
'        
Console.WriteLine("Items in simpleListBox:");
foreach (object item in simpleListBox.Items)
{
    Console.WriteLine(item.GetType().ToString());
}

Console.WriteLine("\rItems in listBoxItemListBox:");

foreach (object item in listBoxItemListBox.Items)
{
    Console.WriteLine(item.GetType().ToString());
}


...


/*
Items in simpleListBox:
System.String
System.Windows.Shapes.Rectangle
System.Windows.Controls.StackPanel
System.DateTime

Items in listBoxItemListBox:
System.Windows.Controls.ListBoxItem
System.Windows.Controls.ListBoxItem
System.Windows.Controls.ListBoxItem
System.Windows.Controls.ListBoxItem
*/

A figura a seguir mostra os dois controles ListBox que foram criados no exemplo anterior.

Compara contêineres de itens explícitos e implícitos

Freqüentemente, você desejará que o contêiner de item para um item. mas você tem não explicitamente criado-lo em seu aplicativo. Para obter o contêiner de itens que está associado a um item específico, use o método ContainerFromItem. O exemplo a seguir mostra como obter um contêiner de itens associado a um item quando um ListBoxItem é criado explicitamente. O exemplo supõe que o objeto chamado itemToSelect não é um ListBoxItem e tenha sido adicionado ao ListBox, simpleListBox.

Dim lbi As ListBoxItem = _
    CType(simpleListBox.ItemContainerGenerator.ContainerFromItem(itemToSelect),  _
          ListBoxItem)

If Not (lbi Is Nothing) Then
    lbi.IsSelected = True
End If
ListBoxItem lbi =
    simpleListBox.ItemContainerGenerator.ContainerFromItem(itemToSelect) 
    as ListBoxItem;

if (lbi != null)
{
    lbi.IsSelected = true;
}

Os estilos que têm TargetType definido como um contêiner de itens são aplicados a contêiners de itens tanto implicitamente quanto explicitamente criados. O exemplo a seguir cria um Style como um recurso para um ListBoxItem que centraliza horizontalmente o conteúdo de ListBoxItem. Quando esse estilo é aplicado aos objetos ListBox, os itens em ambos os objetos ListBox são centralizados.

<!--Create a Style as a Resource.-->
<Style TargetType="ListBoxItem">
  <Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>

A figura a seguir mostra os dois controles ListBox quando o estilo no exemplo anterior é aplicado.

Dois controles de ListBox

O modo como a herança de propriedades funciona com estilos e contêiners de itens está relacionado com como a árvore lógica está estruturada. Quando você criar explicitamente o contêiner de itens, ele é parte da árvore lógica. Se você não criar o contêiner de itens, ele não é parte da árvore lógica. A figura a seguir mostra a diferença na árvore lógica para os dois controles ListBox no exemplo anterior.

Árvores visuais para dois objetos ListBox

Objetos que herdam da classe Visual herdam valores de propriedade de seu pai lógico. O exemplo a seguir cria um ListBox com dois controles TextBlock e define a propriedade Foreground de ListBox para azul. O primeiro TextBlock, textBlock1, está contido em um ListBoxItem criado explicitamente e o segundo TextBlock, textBlock2, não é. O exemplo também define um Style para um ListBoxItem que define o Foreground de um ListBoxItem como verde.

<!--Create a Style as a Resource.-->
<Style TargetType="ListBoxItem">
  <Setter Property="Foreground" Value="Green"/>
</Style>


...


<ListBox Foreground="Blue">
  <ListBoxItem>
    <TextBlock Name="textBlock1">TextBlock in a ListBoxItem.</TextBlock>
  </ListBoxItem>
  <TextBlock Name="textBlock2">TextBlock not in a ListBoxItem.</TextBlock>
</ListBox>

A figura a seguir mostra a ListBox criada no exemplo anterior.

Dois ListBoxItems em um ListBox

A sequência de caracteres textBlock1 é verde e a sequência em textBlock2 é azul porque cada controle TextBlock herda a propriedade Foreground de seu pai lógico respectivo. O pai lógico de textBox1 é o ListBoxItem, e o pai lógico de textBox2 é o ListBox. Para obter mais informações, consulte Herança de Valor de Propriedade.

HeaderedItemsControl

O HeaderedItemsControl herda da classe ItemsControl. The HeaderedItemsControl Define o Header propriedade, que segue sistema autônomo mesmas regras que o Header propriedade de um HeaderedContentControl. WPF três controles que herdam fornecido HeaderedItemsControl:

O seguinte exemplo cria um TreeViewItem. O TreeView contém um único TreeViewItem, que é rotulado TreeViewItem 1 e tem os seguintes itens:

ObservaçãoObservação:

O exemplo cria explicitamente TreeViewItem objetos para os dois últimos itens porque Rectangle e StackPanel herdar a Visual classe. O estilo padrão para o TreeViewItem define a propriedade Foreground. Os objetos filhos herdam o valor da propriedade de TreeViewItem explicitamente criado, que normalmente é o comportamento desejado.

<TreeView xmlns:sys="clr-namespace:System;assembly=mscorlib"
          Margin="10">
  <TreeViewItem Header="TreeViewItem 1" IsExpanded="True">
    TreeViewItem 1a
    <sys:DateTime>2004/3/4 13:6:55</sys:DateTime>
    <TreeViewItem>
      <TreeViewItem.Header>
        <Rectangle Height="10" Width="10" Fill="Blue"/>
      </TreeViewItem.Header>
    </TreeViewItem>
    <TreeViewItem>
      <TreeViewItem.Header>
        <StackPanel Orientation="Horizontal">
          <Ellipse Width="10" Height="10" Fill="DarkGray"/>
          <TextBlock >TreeViewItem 1d</TextBlock>
        </StackPanel>
      </TreeViewItem.Header>
    </TreeViewItem>
  </TreeViewItem>
</TreeView>

Consulte também

Conceitos

Modelo de conteúdo WPF