none
How to change the default item container for ItemsControl?

    Question

  • From what I can tell using Reflector, the ItemsControl returns a ContentPresenter as its item container (while a ListBox returns a ListBoxItem, etc.). I need to implement custom selection logic - rather than using that provided by a Selector - so I was thinking I could just subclass the ItemsControl and force it to use a ListBoxItem as its item container so that I can still get the benefit of the ListBoxItem.IsSelected property.

     

    So far I haven't figured out what all I need to override in order to cause the subclassed ItemsControl to apply something other than the ContentPresenter as its item container...just overriding the GetContainerForItemOverride method apparently isn't enough. Any suggestions?

    Friday, February 29, 2008 9:16 PM

Answers

  • Here's a small example taken from the WPFcontrib project.
    Code Snippet

    /// <summary>
        /// Represents an <see cref="ItemsControl"/> that hosts <see cref="Button"/>s.
        /// </summary>
        public class ButtonList : ItemsControl
        {
            static ButtonList()
            {
                FocusableProperty.OverrideMetadata(typeof(ButtonList), new FrameworkPropertyMetadata(false));
                DefaultStyleKeyProperty.OverrideMetadata(typeof(ButtonList), new FrameworkPropertyMetadata(typeof(ButtonList)));
            }

            /// <summary>
            /// Determines if the specified item is (or is eligible to be) its own container.
            /// </summary>
            /// <param name="item">The item to check.</param>
            /// <returns>
            /// true if the item is (or is eligible to be) its own container; otherwise, false.
            /// </returns>
            protected override bool IsItemItsOwnContainerOverride(object item)
            {
                return item is Button;
            }

            /// <summary>
            /// Creates or identifies the element that is used to display the given item.
            /// </summary>
            /// <returns>
            /// The element that is used to display the given item.
            /// </returns>
            protected override DependencyObject GetContainerForItemOverride()
            {
                return new Button();
            }
        }



    Saturday, March 01, 2008 5:07 PM

All replies

  • Here's a small example taken from the WPFcontrib project.
    Code Snippet

    /// <summary>
        /// Represents an <see cref="ItemsControl"/> that hosts <see cref="Button"/>s.
        /// </summary>
        public class ButtonList : ItemsControl
        {
            static ButtonList()
            {
                FocusableProperty.OverrideMetadata(typeof(ButtonList), new FrameworkPropertyMetadata(false));
                DefaultStyleKeyProperty.OverrideMetadata(typeof(ButtonList), new FrameworkPropertyMetadata(typeof(ButtonList)));
            }

            /// <summary>
            /// Determines if the specified item is (or is eligible to be) its own container.
            /// </summary>
            /// <param name="item">The item to check.</param>
            /// <returns>
            /// true if the item is (or is eligible to be) its own container; otherwise, false.
            /// </returns>
            protected override bool IsItemItsOwnContainerOverride(object item)
            {
                return item is Button;
            }

            /// <summary>
            /// Creates or identifies the element that is used to display the given item.
            /// </summary>
            /// <returns>
            /// The element that is used to display the given item.
            /// </returns>
            protected override DependencyObject GetContainerForItemOverride()
            {
                return new Button();
            }
        }



    Saturday, March 01, 2008 5:07 PM
  • Each ItemsControl has a corresponding Item Container, as illustrated by this table from the MSDN docs:

     

    ItemsControl

    Item container

    ComboBox

    ComboBoxItem

    ContextMenu

    MenuItem

    ListBox

    ListBoxItem

    ListView

    ListViewItem

    Menu

    MenuItem

    StatusBar

    StatusBarItem

    TabControl

    TabItem

    TreeView

    TreeViewItem

     

    It is not readily apparent to me exactly what it is that you are attempting to achieve. Can you provide some more detail on what you are looking to do?

     

    Keith

     

    Saturday, March 01, 2008 7:15 PM
  • This greate Bragi. It's work perfectly. But i face another problem after apply this. Item Container is generated but IsSelected property is not set when Seletor change SelectedIndex. And ItemContainerGenerator.ContainerFromItem always return null. Is there anyway that i can explicitly associate this property with Selector when SelectedIndex is changed.

     

    Regards,

     

    Thursday, March 20, 2008 7:13 AM
  • Are you inheriting from ItemsControl or from Selector?

     

    Thursday, March 20, 2008 8:40 AM
  •  

    Actually my custom control structured like this:

    - MyControl: inherited from Selector

    - MyControl.ItemSource: List<T>

    - MyControl ItemContainer: MyControlItem (inherited from ListBoxItem)

    Then i set default ItemContainer like your instruction above. It's work. But it seems IsSelected of MyControlItem is always reset to false. is there anyway to create MyControlItem explicitly and set IsSelected whenever SelectedIndex of Selector is changed.

     

    Thanks for any advise.

     

    Thursday, March 20, 2008 9:13 AM
  • Haven't done this yet, so no idea.

     

    Thursday, March 20, 2008 9:22 AM