none
ListBoxItem.Selected event not firing on templated ListBox - how come? RRS feed

  • Question

  • Hi - I have a templated ListBox using this code (using techniques described in this CodeProject Article):

    <ListBox Name="listCustomers" Margin="25,210,25,82" ListBoxItem.MouseDoubleClick="listCustomers_MouseDoubleClick"
            ListBoxItem.Selected="listCustomers_Selected" ListBoxItem.Unselected="listCustomers_Unselected"
            IsSynchronizedWithCurrentItem="True" ItemContainerStyle="{StaticResource ListBoxItemStretch}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <controls:myListTemplateControl Margin="4" />
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>


    The ListBoxItem.MouseDoubleClick event is firing ok, but not the ListBoxItem.Selected event. Why would this be happening??


    Monday, August 11, 2008 5:33 PM

Answers

  • The Selected and UnSelected event has been handled by ListBox, you need to specify the event handler with "HandledEventsToo" set to true, the following is a working example:

    <ListBox Name="listData" IsSynchronizedWithCurrentItem="True">
      <ListBox.Resources>
        <Style TargetType="{x:Type ListBoxItem}">
          <EventSetter Event="ListBoxItem.Selected" Handler="ListBoxItem_Selected" HandledEventsToo="True"/>
          <EventSetter Event="ListBoxItem.Unselected" Handler="ListBoxItem_Unselected" HandledEventsToo="True"/>
        </Style>
      </ListBox.Resources>
    </ListBox>

    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            listData.ItemsSource = from i in Enumerable.Range(1, 20) select "Item" + i.ToString();
        }

        private void ListBoxItem_Selected(object sender, RoutedEventArgs e)
        {
            if (!listData.IsLoaded) return;
            MessageBox.Show("You have selected a ListBoxItem!");
        }

        private void ListBoxItem_Unselected(object sender, RoutedEventArgs e)
        {
            if (!listData.IsLoaded) return;
            MessageBox.Show("You have unselected a ListBoxItem!");
        }
    }
    • Marked as answer by Marco Zhou Monday, August 18, 2008 10:11 AM
    Thursday, August 14, 2008 3:15 AM

All replies

  • Could you please provide a small, complete and ready-to-run example to demonstrate the issue you are encountering?

     

    Thanks

    Wednesday, August 13, 2008 7:25 AM
  • Hi Marco - I'll paste in the 4 files needed to recreate this - 1 xaml+cs for the window and 1 xaml+cs for the usercontrol. (I can't see any way to attach the code sample)

    <Window x:Class="WpfListBox.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfListBox"
        Title="Window1" Height="500" Width="400"
        WindowStartupLocation="CenterScreen">

        <Window.Resources>
            <Style x:Key="ListBoxItemStretch" TargetType="{x:Type ListBoxItem}">
                <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                <Setter Property="Background" Value="Transparent" />
            </Style>
        </Window.Resources>
       
        <Grid>
            <ListBox Name="listData" Margin="25,96,25,82" ListBoxItem.MouseDoubleClick="listData_MouseDoubleClick"
                         ListBoxItem.Selected="listData_Selected" ListBoxItem.Unselected="listData_Unselected"
                         IsSynchronizedWithCurrentItem="True" ItemContainerStyle="{StaticResource ListBoxItemStretch}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <local:ListBoxDataItem Margin="4" />
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>
    </Window>


    using System.Collections.ObjectModel;
    using System.Windows;

    namespace WpfListBox
    {
        /// <summary>
        /// Interaction logic for Window1.xaml
        /// </summary>
        public partial class Window1 : Window
        {

            ObservableCollection<DataItem> dataCollection = new ObservableCollection<DataItem>();

            public Window1()
            {
                InitializeComponent();

                dataCollection.Clear();
                dataCollection.Add( new DataItem("John Doe", "55 The Street"));
                dataCollection.Add( new DataItem("Jane Doe", "52 The Street"));
                dataCollection.Add( new DataItem("John Kelly", "51 The Street"));
                dataCollection.Add( new DataItem("Patrick Dunne", "58 The Street"));

                listData.ItemsSource = dataCollection;
            }

            private void listData_Selected(object sender, RoutedEventArgs e)
            {
                MessageBox.Show("You have selected a ListBoxItem!");
            }

            private void listData_Unselected(object sender, RoutedEventArgs e)
            {
                MessageBox.Show("You have unselected a ListBoxItem!");
            }


            private void listData_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
            {
                MessageBox.Show("You have double-clicked a ListBoxItem!");
            }
        }

        public sealed class DataItem
        {

            public string Name { get; set; }
            public string Address { get; set; }

            public DataItem(string name, string address)
            {
                Name = name;
                Address = address;
            }

        }
    }


    <UserControl x:Class="WpfListBox.ListBoxDataItem"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Border BorderThickness="2,2,2,2"
                CornerRadius="5,5,5,5"
                Grid.ColumnSpan="2">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock HorizontalAlignment="Stretch"
                         VerticalAlignment="Stretch"
                         Text="{Binding Path=Name}"
                         TextWrapping="Wrap"
                         Margin="4,4,4,4"
                         Grid.ColumnSpan="1"/>
                <TextBlock HorizontalAlignment="Stretch"
                         VerticalAlignment="Stretch"
                         Text="{Binding Path=Address}"
                         TextWrapping="Wrap"
                         Grid.Column="1"
                         Margin="4,4,4,4"
                         Grid.ColumnSpan="1"/>
            </Grid>
        </Border>
    </UserControl>


    using System.Windows.Controls;

    namespace WpfListBox
    {
        /// <summary>
        /// Interaction logic for ListBoxDataItem.xaml
        /// </summary>
        public partial class ListBoxDataItem : UserControl
        {
            public ListBoxDataItem()
            {
                InitializeComponent();
            }
        }
    }
    • Edited by Neal Hudson Wednesday, August 13, 2008 4:39 PM removing whitespace
    Wednesday, August 13, 2008 4:35 PM
  • The Selected and UnSelected event has been handled by ListBox, you need to specify the event handler with "HandledEventsToo" set to true, the following is a working example:

    <ListBox Name="listData" IsSynchronizedWithCurrentItem="True">
      <ListBox.Resources>
        <Style TargetType="{x:Type ListBoxItem}">
          <EventSetter Event="ListBoxItem.Selected" Handler="ListBoxItem_Selected" HandledEventsToo="True"/>
          <EventSetter Event="ListBoxItem.Unselected" Handler="ListBoxItem_Unselected" HandledEventsToo="True"/>
        </Style>
      </ListBox.Resources>
    </ListBox>

    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            listData.ItemsSource = from i in Enumerable.Range(1, 20) select "Item" + i.ToString();
        }

        private void ListBoxItem_Selected(object sender, RoutedEventArgs e)
        {
            if (!listData.IsLoaded) return;
            MessageBox.Show("You have selected a ListBoxItem!");
        }

        private void ListBoxItem_Unselected(object sender, RoutedEventArgs e)
        {
            if (!listData.IsLoaded) return;
            MessageBox.Show("You have unselected a ListBoxItem!");
        }
    }
    • Marked as answer by Marco Zhou Monday, August 18, 2008 10:11 AM
    Thursday, August 14, 2008 3:15 AM
  • Thanks for clearing it up Marco.

    I do think it's a bit confusing to have a ListBoxItem.Selected available event on the ListBox that never fires though
    Thursday, August 14, 2008 2:16 PM
  • Very much agreed that it makes little sense to have an event that regularly doesn't fire under a very common circumstance.  It certainly seems to violate the "Law of Least Astonishment."  And I dislike any workaround that requires as much ugly, non-intellisense code as the above seems to.  Still, what you gotta do...
    Ken Smith
    Friday, March 20, 2009 3:37 AM