Отвечено How to detect mouse click on ListBox ?

  • Saturday, May 09, 2009 10:12 AM
     
     

    I used SelectionChanged event, but it didn't work when I clicked the same item.

    Then tried to use MouseLeftButtonDown event, but it didn't work at all.

All Replies

  • Saturday, May 09, 2009 2:11 PM
     
     

    Hi,

    The selection changed event only fires when the selection changes, so if you click the same item it doesn't fire.

    In WPF the MouseLeftButtonDown event only fires in areas that wouldn't affect the functionality of the control (i.e. whitespace area between the last item and the horizontal scrollbar.  In Silverlight it doesn't seem to fire at all.

    You can use the MouseLeftButtonUp event if you really need to run some code if the user clicks the same item.  What are you trying to do that can't be handled by the SelectionChanged event?

  • Saturday, May 09, 2009 2:22 PM
     
     Answered

    It's quite a pain...this is the simplest way I could find and it required replacing the ItemTemplate.

            <ListBox>
               
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid Loaded="Grid_Loaded" Background="Orange">
                            <TextBlock Text="{Binding}"/> // replace this with the way you want to display your content
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
               
                <ListBox.Items>
                    <sys:String>one</sys:String>
                    <sys:String>two</sys:String>
                    <sys:String>three</sys:String>
                </ListBox.Items>
            </ListBox>
            

            private void Grid_Loaded(object sender, RoutedEventArgs e)
            {
                // add a handler to the mouse event on the grid...
                // this will run once for each item in the list box so you'll add the same handler to every item
                Grid g = sender as Grid;
                g.MouseLeftButtonDown += Grid_MouseLeftButtonDown;

                // this code I borrowed from another post to stretch the item the full width of the listbox
                // the post is here http://silverlight.net/forums/p/18918/70469.aspx
                FrameworkElement t = sender as FrameworkElement;
                ContentPresenter p = VisualTreeHelper.GetParent(t) as ContentPresenter;
                p.HorizontalAlignment = HorizontalAlignment.Stretch;   
            }

            private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                Grid g = sender as Grid;
                TextBlock tb = g.Children[0] as TextBlock;
                // ...
            }

  • Saturday, May 09, 2009 2:32 PM
     
     
    What does your listitem template look like: Did you put the leftmousebuttondown event on an element within your listboxitem?
  • Saturday, May 09, 2009 4:09 PM
     
     

     

     Try this ListBox Template for the sake of simplicity I used only a TextBlock in this DataTemplate.
    1    <ListBox x:Name="lstCounts">
    2                <ListBox.ItemTemplate>
    3                    <DataTemplate>
    4                        <Border BorderBrush="Brown" CornerRadius="3" BorderThickness="2">
    5                            <TextBlock MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" Text="{Binding }"/>
    6                        </Border>
    7                    </DataTemplate>
    8    </ListBox.ItemTemplate>
    
     in Code Behind File I just populated a list of Numeric strings for ItemSource.
     
    1     List<string> s;
    2    s = new List<string>();
    3    for (int i = 0; i < 20; i++)
    4    {
    5       s.Add(i.ToString());
    6    }
    7    lstCounts.ItemsSource = s;
    
       
    1    private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    2            {
    3                TextBlock txt = sender as TextBlock;            
    4                MessageBox.Show(txt.Text);
    5            }
    
     
     
     

  • Sunday, May 10, 2009 4:24 AM
     
     

    > clint1222:
    > What are you trying to do that can't be handled by the SelectionChanged event?
    I'm trying to open a new page in browser on click on any item. So user could close new page and wanted to open it again. If there is one item only in the list user has no chance to open it twice at all.


    > SharpGIS:
    > Did you put the leftmousebuttondown event on an element within your listboxitem?
    I think so, but I didn't check it well.


    > MarkTap
    Your way works well.


    > inampaki
    Your way has trouble with stretch. If I could set stretch in XAML it might work I think. But I don't know how to do it, so I used MarkTap's way.

  • Sunday, May 10, 2009 4:53 AM
     
     

    > MarkTap

    Now I've got another trouble: Grid_MouseLeftButtonDown() is called when ListBox.SelectedItem is not set yet. So I can't use SelectedItem to know which item was selected. I've fixed it with an additional variable and checking (null == listBox.SelectedItem) but it doesn't seem to be sexy :)

  • Sunday, May 10, 2009 9:07 AM
     
     

    Could you use 'up' instead?

          Grid_Loaded(object sender, RoutedEventArgs e)
          {
                ...
                Grid g = sender as Grid;

                g.MouseLeftButtonUp   += Up;
            }

            void Up(object sender, MouseButtonEventArgs e)
            {
                Grid g = sender as Grid;

                TextBlock tb = g.Children[0] as TextBlock;

                int    index = listbox.SelectedIndex;
                object item  = listbox.SelectedItem;
            }
        }
    }
     

  • Sunday, May 10, 2009 11:25 AM
     
     

     Thanks, my last question was pretty foolish.

    Besides that I have a little other question: I was using background="red" to see the stretch of the container, but since I've removed background from container mouse events are called for container's content only(image, text, etc). Now I'm using background="transparent" to fix it. But may be there is any other way without background option?

  • Sunday, May 10, 2009 4:33 PM
     
     

    Seems like an awful lot of work to get to the MouseLeftButtonUp event.  Why not just handle the MouseLeftButtonUp event on the listbox?

    If you want to open a new browser by clicking on an item in your listbox, why not make the list item a hyperlink button?  You could define it in the datatemplate.  That way you wouldn't have to worry about any listbox click events at all.

  • Sunday, May 10, 2009 11:44 PM
     
     

    Dear Grey Matter

    can u Plz send some ur xaml code so that it could be more clear what u want to do.

  • Monday, May 11, 2009 5:06 AM
     
     

     Thanks a lot for help. I've made HyperlinkButton. It works well.

  • Monday, September 07, 2009 10:05 AM
     
     

    In Silverlight 3 you can do this:

     lstList.AddHandler(FrameworkElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(lstList_MouseLeftButtonDown), true);
     To trap all events, even ones that have been handled. Don't know offhand if it works in earlier versions, though.
  • Thursday, September 24, 2009 7:29 PM
     
     

    I was puzzling over this and then it dawned on me.  You really want to detect the mouse click on the ITEMS of the ListBox.

    I'm adding items to a listbox programmatically and I do this:

    ListBoxItem item = new ListBoxItem();
                    item.Tag = m[0];
                    item.Content = m[1];
                    item.MouseLeftButtonUp += new MouseButtonEventHandler(item_MouseLeftButtonUp);

    The event looks like this:

     void item_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                ListBoxItem item = sender as ListBoxItem;

    ... do something with the item ...

    }

  • Saturday, April 28, 2012 7:23 AM
     
     

    Thanks man!!

    But my question is, how did you figure this out?