System windows controls itemscontrol

Introduction

ItemsControl is a control within the Windows Presentation Foundation (WPF) framework that facilitates the display of a collection of items, which may include data objects or user interface elements. It acts as a foundational class for various other item-oriented controls, such as ListBox, ListView, ComboBox, TreeView, and Menu. Notably, ItemsControl is a more versatile control that does not inherently include specific features for selection, scrolling, or other interactions. Rather, it offers a customizable approach to organizing items through tailored layouts and templates.

Key Properties

  1. ItemsSource: Establishes a connection between the control and a collection of items, which may consist of strings, objects, or any other data source.
  2. ItemTemplate: Determines the visual representation of each item within the collection by utilizing a DataTemplate. For instance, when dealing with custom objects, ItemTemplate can be employed to specify how their properties should be visually represented.
  3. ItemTemplateSelector: Allows for the selection of distinct templates for individual items based on specific criteria. This feature is particularly beneficial when items possess varying layouts or types of content.
  4. ItemsPanel: Specifies the layout panel responsible for organizing the items. Options include using a StackPanel, WrapPanel, or a custom panel to manage the arrangement of items within the ItemsControl.

Key Characteristics of ItemsControl

  1. Versatile Layout: ItemsControl allows for the specification of various layout containers (ItemsPanel), enabling adaptability to different arrangements such as grids, stacks, or bespoke configurations.
  2. Tailored Presentation: Utilizing ItemTemplate and ItemTemplateSelector, you can manage the representation of each item according to its associated data.
  3. Foundation for Specialized Controls: Controls such as ListBox and TreeView derive from ItemsControl, incorporating additional specialized functionalities like item selection and hierarchical organization. ItemsControl is a control within the Windows Presentation Foundation (WPF) framework that facilitates the display of a collection of items, which may include data objects or user interface elements. It acts as a foundational class for various other item-oriented controls, such as ListBox, ListView, ComboBox, TreeView, and Menu. Notably, ItemsControl is a more versatile control that does not inherently include specific features for selection, scrolling, or other interactions. Rather, it offers a customizable approach to organizing items through tailored layouts and templates.

Implementation of ItemsControl

Step 1. Create a Model Class like the one below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TemplateExample
{
    public class DataModel
    {
        public string Label { get; set; }
        public string PropertyType { get; set; } // This will help us select the template
        public string Input { get; set; }
    }
}

Step 2. Create a ViewModel like the one below.

using System.Collections.ObjectModel;

namespace TemplateExample
{
    internal class MainWindowViewModel
    {
        public ObservableCollection<DataModel> ItemsTemplateSourceDataList { get; set; }

        public MainWindowViewModel()
        {
            ItemsTemplateSourceDataList = new ObservableCollection<DataModel>
            {
                new DataModel { Label = "Name", PropertyType = "Text" },
                new DataModel { Label = "Email", PropertyType = "Email" },
                new DataModel { Label = "Phone", PropertyType = "Phone" },
                new DataModel { Label = "Address", PropertyType = "Text" },
                new DataModel { Label = "Comments", PropertyType = "Comments" },
                new DataModel { Label = "Additional Information", PropertyType = "Text" },
                new DataModel { Label = "Feedback", PropertyType = "Comments" }
            };
        }
    }
}

Step 3. Create a template selector like below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows;

namespace TemplateExample
{
    public class PropertyTemplateSelector : DataTemplateSelector
    {
        public DataTemplate TextTemplate { get; set; }
        public DataTemplate EmailTemplate { get; set; }
        public DataTemplate PhoneTemplate { get; set; }
        public DataTemplate CommentsTemplate { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (item is DataModel DataModel)
            {
                switch (DataModel.PropertyType)
                {
                    case "Text":
                        return TextTemplate;
                    case "Email":
                        return EmailTemplate;
                    case "Phone":
                        return PhoneTemplate;
                    case "Comments":
                        return CommentsTemplate;
                    default:
                        return base.SelectTemplate(item, container);
                }
            }
            return base.SelectTemplate(item, container);
        }
    }
}

Step 4. Define the DataTemplate in XAML.

<Window x:Class="TemplateExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TemplateExample"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.Resources>
        <!-- Template for Text Property -->
        <DataTemplate x:Key="TextTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" SharedSizeGroup="LabelGroup" />
                    <ColumnDefinition Width="5" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="30" />
                </Grid.RowDefinitions>
                <TextBlock Text="{Binding Label}" FontSize="14" Margin="5" Grid.Column="0" Grid.Row="0" />
                <GridSplitter Width="5" Background="DarkGray" HorizontalAlignment="Stretch" Grid.Column="1" ResizeDirection="Columns" Grid.Row="0" />
                <TextBox Text="{Binding Input}" Margin="5" Grid.Column="2" HorizontalAlignment="Stretch" Grid.Row="0" />
            </Grid>
        </DataTemplate>

        <!-- Template for Email Property -->
        <DataTemplate x:Key="EmailTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" SharedSizeGroup="LabelGroup" />
                    <ColumnDefinition Width="5" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <TextBlock Text="{Binding Label}" FontSize="14" Margin="5" Grid.Column="0" />
                <GridSplitter Width="5" Background="DarkGray" HorizontalAlignment="Stretch" Grid.Column="1" ResizeDirection="Columns" />
                <TextBox Text="{Binding Input}" Margin="5" Grid.Column="2" HorizontalAlignment="Stretch" />
            </Grid>
        </DataTemplate>

        <!-- Template for Phone Property -->
        <DataTemplate x:Key="PhoneTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" SharedSizeGroup="LabelGroup" />
                    <ColumnDefinition Width="5" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <TextBlock Text="{Binding Label}" FontSize="14" Margin="5" Grid.Column="0" />
                <GridSplitter Width="5" Background="DarkGray" HorizontalAlignment="Stretch" Grid.Column="1" ResizeDirection="Columns" />
                <TextBox Text="{Binding Input}" Margin="5" Grid.Column="2" HorizontalAlignment="Stretch" />
            </Grid>
        </DataTemplate>

        <!-- Template for Comments (Multi-line Text) Property -->
        <DataTemplate x:Key="CommentsTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" SharedSizeGroup="LabelGroup" />
                    <ColumnDefinition Width="5" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <TextBlock Text="{Binding Label}" FontSize="14" Margin="5" Grid.Column="0" />
                <GridSplitter Width="5" Background="DarkGray" HorizontalAlignment="Stretch" Grid.Column="1" ResizeDirection="Columns" />
                <TextBox Text="{Binding Input}" Margin="5" Grid.Column="2" AcceptsReturn="True" Height="100" HorizontalAlignment="Stretch" />
            </Grid>
        </DataTemplate>

        <!-- DataTemplateSelector for Choosing Template Based on PropertyType -->
        <local:PropertyTemplateSelector x:Key="SettingTemplateSelector"
                                        TextTemplate="{StaticResource TextTemplate}"
                                        EmailTemplate="{StaticResource EmailTemplate}"
                                        PhoneTemplate="{StaticResource PhoneTemplate}"
                                        CommentsTemplate="{StaticResource CommentsTemplate}" />
    </Window.Resources>

    <!-- ItemsControl with ScrollViewer -->
    <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
        <Grid IsSharedSizeScope="True" HorizontalAlignment="Stretch">
            <ItemsControl x:Name="SettingsItemsPanel"
                          ItemsSource="{Binding ItemsTemplateSourceDataList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                          ItemTemplateSelector="{StaticResource SettingTemplateSelector}">
            </ItemsControl>
        </Grid>
    </ScrollViewer>
</Window>

Step 5. Set the Window’s DataContext (in Code-Behind).

using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace TemplateExample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainWindowViewModel();
        }
    }
}

Step 6. The output will appear as follows.

Output

Элементы управления списками

Последнее обновление: 28.01.2023

Эти элементы представлены в WPF довольно широко. Все они являются производными от класса ItemsControl,
который в свою очередь является наследником класса Control. Все они содержат коллекцию элементов. Элементы могут быть напрямую добавлены в коллекцию,
возможна также привязка некоторого массива данных к коллекции.

Возьмем простейший элемент-список — ListBox и определим в файле MainWindow.xaml следующий интерфейс:

<Window x:Class="MetanitApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:local="clr-namespace:MetanitApp"
        mc:Ignorable="d"
        Name="MainWindow" Height="200" Width="300">
    <ListBox x:Name="usersList">
        <sys:String>Tom</sys:String>
        <sys:String>Bob</sys:String>
        <sys:String>Sam</sys:String>
        <sys:String>Alice</sys:String>
    </ListBox>
</Window>

Все элементы, размещенные внутри спискового элемента ListBox, представляют элементы списка.

Управление списком

Коллекция объектов внутри элемента-списка доступна в виде свойства Items. Для управления элементами из этой коллекции мы можем использовать следующие методы:

  • Add(object item): добавление элемента
  • Clear(): полная очистка коллекции
  • Insert(int index, object item): вставка элемента по определенному индексу в коллекции
  • Remove(object item): удаление элемента
  • RemoveAt(int index): удаление элемента по индексу

А свойство Count позволяет узнать, сколько элементов в коллекции.

Например, оставим предыдущий интерфейс и в файле связанного кода MainWindow.xaml.cs добавим и удалим программно несколько элементов:

using System.Windows;
namespace MetanitApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            usersList.Items.Remove("Sam");      // удаляем элемент "Sam"
            usersList.Items.RemoveAt(1);        // удаляем второй элемент
            usersList.Items.Add("Kate");        // Добавляем элемент "Kate"
            usersList.Items.Insert(0, "Mike"); // Вставляем элемент "Mike" на первое место в списке
        }
    }
}

В данном случае добавляем и удаляем ряд элементов с помощью различных методов и в итоге получим следующий список:

При вызове методов, которые используют индексы, как выше методы RemoveAt(index) и Insert(index, object), следует учитывать, что передаваемые индексы
должны быть действительны. Естественно мы не можем удалить, к примеру, второй объект, если списке только один объект или вообще нет объектов. В этом случае мы можем проверять
длину списка:

if(usersList.Items.Count > 1)    // если в списке больше 1 элемента
 {
    usersList.Items.Insert(1, "Mike"); // Вставляем элемент "Mike" на второе место
    usersList.Items.RemoveAt(2);    // удаляем третий элемент
}

Отображение сложных данных

Списковые элементы могут отображать не только простые строки или числа, но и сложные данные. Например, создадим в коде новый класс Person:

public class Person
{
    public string Name { get; set; } = "";
    public int Age { get; set; }

    public override string ToString()
    {
        return $"Name: {Name}  Age: {Age}";
    }
} 

Теперь создадим в xaml набор объектов этого класса Person и выведем в их в списке:

<Window x:Class="MetanitApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:local="clr-namespace:MetanitApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="300">
    <ListBox x:Name="usersList">
        <local:Person Name="Tom" Age="38" />
        <local:Person Name="Bob" Age="42" />
        <local:Person Name="Sam" Age="25" />
        <local:Person Name="Alice" Age="34" />
    </ListBox>
</Window>

Поскольку мы используем класс, определенный в текущем проекте, то соответственно у нас обязательно должно быть подключено пространство имен проекте.
В моем случае проект (и пространство имен) называется «MetanitApp». Соответственно у меня это пространство имен проецируется на префикс local:

xmlns:local="clr-namespace:MetanitApp"

В принципе по умолчанию WPF уже его подключает. После этого через префикс «local» можно обращаться к классу Person: «local:Person».

Кроме того, чтобы не возникало проблем с разметкой XAML, желательно сделать перестроение проекта. И в итоге ListBox выведет все объекты:

По умолчанию списковые элементы выводят то, что возвращает метод ToString() объекта. Именно для этой демонстрации и реализован данный метод в классе Person выше.
Но также с помощью свойства DisplayMemberPath можно установить свойство объекта, значение которого будет отображаться в списке. Например, отобразим только имя:

<Window x:Class="MetanitApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MetanitApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="300">
    <ListBox x:Name="usersList" DisplayMemberPath="Name">
        <local:Person Name="Tom" Age="38" />
        <local:Person Name="Bob" Age="42" />
        <local:Person Name="Sam" Age="25" />
        <local:Person Name="Alice" Age="34" />
    </ListBox>
</Window>

В этом случае в коде C# таким же образом можно добавлять и удалять данные:

var firstPerson = usersList.Items[0];   // получаем первый объект
usersList.Items.Remove(firstPerson);    // удаляем его
usersList.Items.Add(new Person { Name = "Kate", Age = 23 }); // добавляем новый объект

ItemsSource

Нам необязательно вручную заполнять значения элемента управления списком, так как мы можем установить свойство ItemsSource,
задав в качестве параметра коллекцию, из которой будет формироваться элемент управления списком. Например, в коде xaml-разметки определим пустой список:

<Window x:Class="MetanitApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="300">

    <ListBox x:Name="usersList" />

</Window>

А в файле отделенного кода выполним наполнение списка:

using System.Windows;
using System.Collections.Generic;

namespace MetanitApp;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        usersList.ItemsSource = new List<Person>()
        {
            new Person{Name="Tom", Age=38},
            new Person {Name="Bob", Age=42},
            new Person{Name="Sam", Age=25}
        };
        // устанавливаем отображаемое свойство
        usersList.DisplayMemberPath = "Name";
    }
}

Но стоит учитывать, что если мы наполняем элемент управления списком через свойство ItemsSource, то мы не сможем использовать
выше рассмотренные методы Add/Remove/RemoveAt/Insert/Clear для добавления/удаления элементов списка. В этом случае для управления элементами непосредственно к самому источнику данных.
Например, определим в коде xaml кнопку для добавления одного объекта:

<Window x:Class="MetanitApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="300">
    <StackPanel>
        <ListBox x:Name="usersList" DisplayMemberPath="Name" />
        <Button Content="Add" Click="Button_Click" Margin="5" Width="80" HorizontalAlignment="Left" />
    </StackPanel>
</Window>

По нажатию на кнопку будет вызываться метод Button_Click. И в файле связанного кода C# определим данный метод и наполним ListBox данными:

using System.Windows;
using System.Collections.Generic;

namespace MetanitApp;

public partial class MainWindow : Window
{
    List<Person> people = new List<Person>()
        {
            new Person{Name="Tom", Age=38},
            new Person {Name="Bob", Age=42},
            new Person{Name="Sam", Age=25}
        };
    public MainWindow()
    {
        InitializeComponent();
        usersList.ItemsSource = people;
    }
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        people.Add(new Person { Name = "Mike", Age = 29 });
        usersList.Items.Refresh();
    }
}

Здесь в качестве источника данных выступает список people, и из этого списка ListBox будет брать данные.

В обработчике нажатия кнопки добавляем в список people один объект Person для теста. Обратите внимание, что добавляем именно в стандартный список List<Person>,
а не в ListBox. ListBox в данном случае просто отображает данные. Но чтобы ListBox обновил свое визуальное представление, после изменения списка people обновляем данные в ListBox:

usersList.Items.Refresh();

Обновление данных в ListBox в WPF и C#

Стоит отметить, что если в качестве источника данных выступает ObservableCollection, то нам не надо вызывает отобновление данных списка, так как коллекция ObservableCollection сама извещает систему
об изменениях.

Выбор элементов

Все элементы управления списками поддерживают выделение входящих элементов. Выделенный элемент(ы) можно получить с помощью свойств
SelectedItem(SelectedItems), а получить индекс выделенного элемента — с помощью свойства SelectedIndex.
Свойство SelectedValue позволяет получить значение выделенного элемента.

При выделении элемента в списке генерируется событие SelectionChanged, которое мы можем обработать. Например, возьмем предыдущий список:

<Window x:Class="MetanitApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MetanitApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="300">
    <ListBox x:Name="usersList" DisplayMemberPath="Name" SelectionChanged="usersList_SelectionChanged">
        <local:Person Name="Tom" Age="38" />
        <local:Person Name="Bob" Age="42" />
        <local:Person Name="Sam" Age="25" />
        <local:Person Name="Alice" Age="34" />
    </ListBox>
</Window>

А в файле кода определим обработчик для этого события:

using System.Windows;
using System.Windows.Controls;

namespace MetanitApp;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
    private void usersList_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (usersList.SelectedItem is Person person)
        {
            MessageBox.Show(person.Name);
        }
    }
}

Важно учитывать, что так как в разметке xaml в списке определены элементы Person, то в коде мы можем привести объект usersList.SelectedItem к типу Person.

Represents a control that can be used to present a collection of items.

Inheritance

System.Object

ItemsControl

Inherited Members

System.Object.Equals(System.Object)

System.Object.Equals(System.Object, System.Object)

System.Object.GetHashCode()

System.Object.GetType()

System.Object.MemberwiseClone()

System.Object.ReferenceEquals(System.Object, System.Object)

System.Object.ToString()

Namespace: System.Windows.Controls
Assembly: OpenSilver.dll
Syntax
public class ItemsControl : Control, IControl, IFrameworkElement, IUIElement, IDependencyObject

Constructors


|
Improve this Doc


View Source

ItemsControl()

Initializes a new instance of the ItemsControl class.

Declaration

Fields


|
Improve this Doc


View Source

DisplayMemberPathProperty

Identifies the DisplayMemberPath dependency property.

Declaration
public static readonly DependencyProperty DisplayMemberPathProperty

Field Value
Type Description
DependencyProperty


|
Improve this Doc


View Source

ItemContainerStyleProperty

Identifies the ItemContainerStyle dependency property.

Declaration
public static readonly DependencyProperty ItemContainerStyleProperty

Field Value
Type Description
DependencyProperty


|
Improve this Doc


View Source

ItemsPanelProperty

Identifies the ItemsPanel dependency property.

Declaration
public static readonly DependencyProperty ItemsPanelProperty

Field Value
Type Description
DependencyProperty


|
Improve this Doc


View Source

ItemsSourceProperty

Identifies the ItemsSource dependency property.

Declaration
public static readonly DependencyProperty ItemsSourceProperty

Field Value
Type Description
DependencyProperty


|
Improve this Doc


View Source

ItemTemplateProperty

Identifies the ItemTemplate dependency property.

Declaration
public static readonly DependencyProperty ItemTemplateProperty

Field Value
Type Description
DependencyProperty

Properties


|
Improve this Doc


View Source

DisplayMemberPath

Gets or sets a path to a value on the source object to serve as the visual
representation of the object.

Declaration
public string DisplayMemberPath { get; set; }

Property Value
Type Description
System.String


|
Improve this Doc


View Source

ItemContainerGenerator

Gets the ItemContainerGenerator associated with this ItemsControl.

Declaration
public ItemContainerGenerator ItemContainerGenerator { get; }

Property Value
Type Description
ItemContainerGenerator


|
Improve this Doc


View Source

ItemContainerStyle

Gets or sets the style that is used when rendering the item containers.

Declaration
public Style ItemContainerStyle { get; set; }

Property Value
Type Description
Style


|
Improve this Doc


View Source

Items

Items is the collection of data that is used to generate the content
of this control.

Declaration
public ItemCollection Items { get; }

Property Value
Type Description
ItemCollection


|
Improve this Doc


View Source

ItemsPanel

Gets or sets the template that defines the panel that controls the layout
of items.

Declaration
public ItemsPanelTemplate ItemsPanel { get; set; }

Property Value
Type Description
ItemsPanelTemplate


|
Improve this Doc


View Source

ItemsSource

Gets or sets an object source used to generate the content of the ItemsControl.

Declaration
public IEnumerable ItemsSource { get; set; }

Property Value
Type Description
System.Collections.IEnumerable


|
Improve this Doc


View Source

ItemTemplate

Gets or sets the DataTemplate used to display each item.

Declaration
public DataTemplate ItemTemplate { get; set; }

Property Value
Type Description
DataTemplate


|
Improve this Doc


View Source

LogicalChildren

Gets an enumerator for the logical child objects of the ItemsControl object.

Declaration
protected override IEnumerator LogicalChildren { get; }

Property Value
Type Description
System.Collections.IEnumerator

An enumerator for the logical child objects of the ItemsControl object.
The default is null.

Overrides

Methods


|
Improve this Doc


View Source

ClearContainerForItemOverride(DependencyObject, Object)

Undoes the effects of the PrepareContainerForItemOverride method.

Declaration
protected virtual void ClearContainerForItemOverride(DependencyObject element, object item)

Parameters
Type Name Description
DependencyObject element

The container element.

System.Object item

The item.


|
Improve this Doc


View Source

GetContainerForItemOverride()

Creates or identifies the element that is used to display the given item.

Declaration
protected virtual DependencyObject GetContainerForItemOverride()

Returns
Type Description
DependencyObject

The element that is used to display the given item.


|
Improve this Doc


View Source

GetItemsOwner(DependencyObject)

Declaration
public static ItemsControl GetItemsOwner(DependencyObject element)

Parameters
Type Name Description
DependencyObject element
Returns
Type Description
ItemsControl


|
Improve this Doc


View Source

IsItemItsOwnContainerOverride(Object)

Determines whether the specified item is (or is eligible to be) its
own container.

Declaration
protected virtual bool IsItemItsOwnContainerOverride(object item)

Parameters
Type Name Description
System.Object item

The item to check.

Returns
Type Description
System.Boolean

True if the item is (or is eligible to be) its own container; otherwise,
false.


|
Improve this Doc


View Source

ItemsControlFromItemContainer(DependencyObject)

Declaration
public static ItemsControl ItemsControlFromItemContainer(DependencyObject container)

Parameters
Type Name Description
DependencyObject container
Returns
Type Description
ItemsControl


|
Improve this Doc


View Source

OnItemsChanged(NotifyCollectionChangedEventArgs)

Called when the value of the Items property changes.

Declaration
protected virtual void OnItemsChanged(NotifyCollectionChangedEventArgs e)

Parameters
Type Name Description
System.Collections.Specialized.NotifyCollectionChangedEventArgs e

A System.Collections.Specialized.NotifyCollectionChangedEventArgs that contains the event data


|
Improve this Doc


View Source

OnItemsSourceChanged(IEnumerable, IEnumerable)

Declaration
protected virtual void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)

Parameters
Type Name Description
System.Collections.IEnumerable oldValue
System.Collections.IEnumerable newValue


|
Improve this Doc


View Source

OnTextInput(TextCompositionEventArgs)

Declaration
protected override void OnTextInput(TextCompositionEventArgs e)

Parameters
Type Name Description
TextCompositionEventArgs e
Overrides


|
Improve this Doc


View Source

PrepareContainerForItemOverride(DependencyObject, Object)

Prepares the specified element to display the specified item.

Declaration
protected virtual void PrepareContainerForItemOverride(DependencyObject element, object item)

Parameters
Type Name Description
DependencyObject element

The element that’s used to display the specified item.

System.Object item

The item to display.


|
Improve this Doc


View Source

UpdateItemsPanel(ItemsPanelTemplate)

Declaration
protected virtual void UpdateItemsPanel(ItemsPanelTemplate newTemplate)

Parameters
Type Name Description
ItemsPanelTemplate newTemplate

Extension Methods

ItemsControl

System.Object
    System.Windows.Threading.DispatcherObject
        System.Windows.DependencyObject
            System.Windows.Media.Visual
                System.Windows.UIElement
                    System.Windows.FrameworkElement
                        System.Windows.Controls.Control
                            System.Windows.Controls.ItemsControl

ItemsControl is the base class
for all controls that present lists or trees of items, including
ListBox, TreeView, and Menu. Because it is a concrete class, it can
also be used in its own right. ItemsControl provides item presentation and
data binding support, but does not offer item selection—this lets you
present a list of items without being forced to make them selectable.
Use the Selector base class if you
require selection.

Chapter 5 describes how to use ItemsControl and the various list controls
derived from it. Chapter 7 describes how
to use data binding with these controls.

I wanted to highlight some of the similarities and some of the differences of ListBox vs ItemsControl.

Similarites of ItemsControl, ListBox, and ListView

These two controls are similar in a few ways.

  • All three are lists
  • All three support binding ItemsSource to a list
  • All three are ItemsControl objects as ListBox and ListView are descendants

Differences between ItemsControl, ListBox, and ListView

Inheritence

ItemsControl

ItemsControl uses an ItemsPresenter to present its children.

System.Object
System.Windows.Threading.DispatcherObject
System.Windows.DependencyObject
System.Windows.Media.Visual
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Control
System.Windows.Controls.ItemsControl

ListBox

A ListBox is an ItemsControl but an ItemsControl is not a list box. Notice a list box is a descendant of ItemsControl but has a Selector object, which is abstract, that it specifically derives from. Inheriting from Selector provides ListBox with selection events and selection features that are missing from ItemsControl. ListBox adds a SelectionMode Dependency Property that allows for selection types of Single, Multiple, or Extended, which are defined in a SelectionMode enum. It uses ListBoxItem as its default child.


System.Windows.Controls.ItemsControl
System.Windows.Controls.Primitives.Selector
System.Windows.Controls.ListBox

ListView

ListView inherits from ListBox, so it is everything a ListBox is plus it has a View Dependency Property and some functions supporting the View Dependency Property. It uses ListViewItem as its default child.


System.Windows.Controls.ItemsControl
System.Windows.Controls.Primitives.Selector
System.Windows.Controls.ListBox
System.Windows.Controls.ListView

Sizing and Scrolling

  • ItemsControl takes as much space as it needs for its child elements, which can cause it to be larger than the screen. Because its size is based on its child controls, ItemsControl does not resize when re-sizing the screen.
  • ListBox and ListView take up all the space available to them from the parent and no more. Because the size is based on the parent control size, ListBox and ListView resize with the screen.
  • ItemsControl does not have a ScrollBar.
  • ListBox has both a vertical and horizontal ScrollBar.

Note: I learned that if you want to have an ItemsControl, but you want to have the scrolling. Simply make a copy of the ListBox style and change its TargetType to ItemsControl and use that style.

Styles and Templates

Note: These default styles are obtained using Expresion Blend by right-clicking a Control and choosing Edit Template | Edit a copy.

ItemsControl Default Style

This style is short and simple.

<ResourceDictionary
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
	<Style x:Key="ItemsControlDefaultStyle" TargetType="{x:Type ItemsControl}">
		<Setter Property="Template">
			<Setter.Value>
				<ControlTemplate TargetType="{x:Type ItemsControl}">
					<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
						<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
					</Border>
				</ControlTemplate>
			</Setter.Value>
		</Setter>
	</Style>
	<!-- Resource dictionary entries should be defined here. -->
</ResourceDictionary>

ListBox and ListView Default Style

ListBox and ListView have the same default style, with the only exception being the the TargetType, which is of course ListBox or ListView repectively.

Both have all the elements ItemsControl has, but also there are more Setters as Setters exist for the ScrollViewer and for the Border. ListBox and ListView styles also include a ScrollViewer in the ControlTemplate between the Border and the ItemsPresenter. ListBox and ListView also have a ControlTemplate.Triggers section.

<ResourceDictionary
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
	<SolidColorBrush x:Key="ListBorder" Color="#828790"/>
	<Style x:Key="ListBoxDefaultStyle" TargetType="{x:Type ListBox}">
		<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
		<Setter Property="BorderBrush" Value="{StaticResource ListBorder}"/>
		<Setter Property="BorderThickness" Value="1"/>
		<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
		<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
		<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
		<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
		<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
		<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
		<Setter Property="VerticalContentAlignment" Value="Center"/>
		<Setter Property="Template">
			<Setter.Value>
				<ControlTemplate TargetType="{x:Type ListBox}">
					<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1" SnapsToDevicePixels="true">
						<ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
							<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
						</ScrollViewer>
					</Border>
					<ControlTemplate.Triggers>
						<Trigger Property="IsEnabled" Value="false">
							<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
						</Trigger>
						<Trigger Property="IsGrouping" Value="true">
							<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
						</Trigger>
					</ControlTemplate.Triggers>
				</ControlTemplate>
			</Setter.Value>
		</Setter>
	</Style>
	<!-- Resource dictionary entries should be defined here. -->
</ResourceDictionary>

Note: If you accidentally put ListBoxItems under ListView, the items are wrapped in a ListViewItem control which has its own margin, which will make the items move 5 pixels further to the right.

Choosing betweeen ItemsControl, ListBox, and ListView

Choosing an ItemsControl

It is pretty easy to choose between ItemsControl and either ListBox or ListView. If you do not want the ability to select a row or switch the View, use ItemsControl. Otherwise, use ListBox or ListView.

Choosing an ListBox

Also, if you need the select feature but you do not need to be able to switch the View, use ListBox.

Choosing an ListView

If you need to be able to switch the View, then choose ListView. It doesn’t matter if you need the ability to select or not.

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Какой командлет windows powershell является аналогом утилиты командной строки gpupdate
  • Как убрать заставку на экране блокировки windows 10
  • Ошибка bugcode usb driver windows 8
  • Как починить системные файлы windows 10
  • Windows 7 loader from matrix