Rafael
Rafael

Reputation: 85

How add the event of mouse over in a ListBox on Code Behind

private ListBox linkList = new ListBox();

here I want to add the event of mouseOver for each item from the linkList

I tried:

foreach(ListItem item in linkList.Items){
    ...
}

but didn't work what can I do?

this is how the ListBox is filling :

<ListBox x:Name="LinkList" ItemsSource="{TemplateBinding Links}"  
            ScrollViewer.HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid Height="50" Background="Transparent" Width="500">
                <Border Padding="10">
                    <Path x:Name="icon" Data="{Binding IconData}" Stretch="Fill" Fill="{DynamicResource Accent}" Width="20" Height="20" HorizontalAlignment="Left" VerticalAlignment="Center" />
                </Border>
                <TextBlock x:Name="texto" ToolTip="{Binding Tooltip}"  Text="{Binding DisplayName}" Margin="45,2,2,2" FontSize="{DynamicResource MediumFontSize}" TextTrimming="CharacterEllipsis" VerticalAlignment="Center" HorizontalAlignment="Left" />
            </Grid>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding IconData}" Value="{x:Null}">
                    <Setter Property="Margin" TargetName="texto">
                        <Setter.Value>
                            <Thickness Bottom="2" Top="2" Left="10" Right="2"/> 
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
                <Trigger Property="IsMouseOver" Value="true">
                    <Setter Property="Fill" TargetName="icon">
                        <Setter.Value>
                            <SolidColorBrush Color="#f2f2f2" />
                        </Setter.Value>
                    </Setter>
                </Trigger>

            </DataTemplate.Triggers>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Update:

Code Behind:

public partial class ModernVerticalMenu
    : Control
{
    /// <summary>
    /// Identifies the ContentLoader dependency property.
    /// </summary>
    public static readonly DependencyProperty ContentLoaderProperty = DependencyProperty.Register("ContentLoader", typeof(IContentLoader), typeof(ModernVerticalMenu), new PropertyMetadata(new DefaultContentLoader()));
    /// <summary>
    /// Identifies the Layout dependency property.
    /// </summary>
    public static readonly DependencyProperty LayoutProperty = DependencyProperty.Register("Layout", typeof(TabLayout), typeof(ModernVerticalMenu), new PropertyMetadata(TabLayout.Tab));
    /// <summary>
    /// Identifies the ListWidth dependency property.
    /// </summary>
    public static readonly DependencyProperty ListWidthProperty = DependencyProperty.Register("ListWidth", typeof(GridLength), typeof(ModernVerticalMenu), new PropertyMetadata(new GridLength(170)));
    /// <summary>
    /// Identifies the Links dependency property.
    /// </summary>
    public static readonly DependencyProperty LinksProperty = DependencyProperty.Register("Links", typeof(LinkCollection), typeof(ModernVerticalMenu), new PropertyMetadata(OnLinksChanged));
    /// <summary>
    /// Identifies the SelectedSource dependency property.
    /// </summary>
    public static readonly DependencyProperty SelectedSourceProperty = DependencyProperty.Register("SelectedSource", typeof(Uri), typeof(ModernVerticalMenu), new PropertyMetadata(OnSelectedSourceChanged));
    /// <summary>
    /// Defines the SelectedLinkGroup dependency property.
    /// </summary>
    public static readonly DependencyProperty SelectedLinkGroupProperty = DependencyProperty.Register("SelectedLinkGroup", typeof(LinkCollection), typeof(ModernVerticalMenu), new PropertyMetadata(OnSelectedLinkGroupChanged));
    /// <summary>
    /// Defines the SelectedLink dependency property.
    /// </summary>
    public static readonly DependencyProperty SelectedLinkProperty = DependencyProperty.Register("SelectedLink", typeof(Link), typeof(ModernVerticalMenu), new PropertyMetadata(OnSelectedLinkChanged));


    /// <summary>
    /// Occurs when the selected source has changed.
    /// </summary>
    public event EventHandler<SourceEventArgs> SelectedSourceChanged;

    private ListBox linkList;

    /// <summary>
    /// Initializes a new instance of the <see cref="ModernVerticalMenu"/> control.
    /// </summary>
    public ModernVerticalMenu()
    {
        this.DefaultStyleKey = typeof(ModernVerticalMenu);

        // create a default links collection
        SetCurrentValue(LinksProperty, new LinkCollection());
    }

    private static void OnSelectedLinkGroupChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        // retrieve the selected link from the group
        var group = (Link)e.NewValue; // cria uma nova instancia do grupo
        Link selectedLink = null; //cria um link selecionado
        if (group != null)
        { //se o grupo copiado existe
            selectedLink = group; //

            // if no link selected or link doesn't exist in group links, auto-select first
            if (group.Children != null)
            {
                if (selectedLink != null && !group.Children.Any(l => l == selectedLink))
                {
                    selectedLink = null;
                }

                if (selectedLink == null)
                {
                    selectedLink = group.Children.FirstOrDefault();
                }
            }
        }

        // update the selected link
        ((ModernVerticalMenu)o).SetCurrentValue(SelectedLinkProperty, selectedLink);
    }

    private static void OnSelectedLinkChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        // update selected source
        var newValue = (Link)e.NewValue;
        Uri selectedSource = null;
        if (newValue != null)
        {
            selectedSource = newValue.Source;
        }
        ((ModernVerticalMenu)o).SetCurrentValue(SelectedSourceProperty, selectedSource);
    }


    private static void OnLinksChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        ((ModernVerticalMenu)o).UpdateSelection();
    }

    private static void OnSelectedSourceChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        ((ModernVerticalMenu)o).OnSelectedSourceChanged((Uri)e.OldValue, (Uri)e.NewValue);
    }

    private void OnSelectedSourceChanged(Uri oldValue, Uri newValue)
    {
        UpdateSelection();

        // raise SelectedSourceChanged event
        var handler = this.SelectedSourceChanged;
        if (handler != null) {
            handler(this, new SourceEventArgs(newValue));
        }
    }

    private void UpdateSelection()
    {
        if (this.linkList == null || this.Links == null) {
            return;
        }

        // sync list selection with current source

        this.linkList.SelectedItem = this.Links.FirstOrDefault(l => l.Source == this.SelectedSource);
        SetValue(SelectedLinkGroupProperty, this.Links.FirstOrDefault(l => l.Children == this.SelectedLinkGroup));
        if (this.Links.FirstOrDefault(l => l.Children == this.SelectedLinkGroup) != null)
            MessageBox.Show(this.Links.FirstOrDefault(l => l.Children == this.SelectedLinkGroup).Children.Count.ToString());
    }

    /// <summary>
    /// When overridden in a derived class, is invoked whenever application code or internal processes call System.Windows.FrameworkElement.ApplyTemplate().
    /// </summary>
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        if (this.linkList != null) {
            this.linkList.SelectionChanged -= OnLinkListSelectionChanged;
        }

        this.linkList = GetTemplateChild("LinkList") as ListBox;
        if (this.linkList != null) {
            this.linkList.SelectionChanged += OnLinkListSelectionChanged;
        }

        UpdateSelection();
    }

    private void OnLinkListSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var link = this.linkList.SelectedItem as Link;
        if (link != null && link.Source != this.SelectedSource) {
            SetCurrentValue(SelectedSourceProperty, link.Source);
        }
    }

    /// <summary>
    /// Gets or sets the content loader.
    /// </summary>
    public IContentLoader ContentLoader
    {
        get { return (IContentLoader)GetValue(ContentLoaderProperty); }
        set { SetValue(ContentLoaderProperty, value); }
    }

    /// <summary>
    /// Gets or sets a value indicating how the tab should be rendered.
    /// </summary>
    public TabLayout Layout
    {
        get { return (TabLayout)GetValue(LayoutProperty); }
        set { SetValue(LayoutProperty, value); }
    }

    /// <summary>
    /// Gets or sets the collection of links that define the available content in this tab.
    /// </summary>
    public LinkCollection Links
    {
        get { return (LinkCollection)GetValue(LinksProperty); }
        set { SetValue(LinksProperty, value); }
    }

    /// <summary>
    /// Gets or sets the collection of links that define the available content in this tab.
    /// </summary>
    public LinkCollection SelectedLinkGroup
    {
        get { return (LinkCollection)GetValue(SelectedLinkGroupProperty); }
        set { SetValue(SelectedLinkGroupProperty, value); }
    }

    /// <summary>
    /// Gets or sets the collection of links that define the available content in this tab.
    /// </summary>
    public Link SelectedLink
    {
        get { return (Link)GetValue(SelectedLinkProperty); }
        set { SetValue(SelectedLinkProperty, value); }
    }

    /// <summary>
    /// Gets or sets the width of the list when Layout is set to List.
    /// </summary>
    /// <value>
    /// The width of the list.
    /// </value>
    public GridLength ListWidth
    {
        get { return (GridLength)GetValue(ListWidthProperty); }
        set { SetValue(ListWidthProperty, value); }
    }

    /// <summary>
    /// Gets or sets the source URI of the selected link.
    /// </summary>
    /// <value>The source URI of the selected link.</value>
    public Uri SelectedSource
    {
        get { return (Uri)GetValue(SelectedSourceProperty); }
        set { SetValue(SelectedSourceProperty, value); }
    }
}

this causes compilation's errors because of the conflict of base classes(ResourceDictionary and Control)

All XAML:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:controls="clr-namespace:FirstFloor.ModernUI.Windows.Controls" x:Class="FirstFloor.ModernUI.Windows.Controls.ModernVerticalMenu">

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/Converters.xaml" />
</ResourceDictionary.MergedDictionaries>

<Style TargetType="controls:ModernVerticalMenu" >
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="controls:ModernVerticalMenu">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="{TemplateBinding ListWidth}"/>
                        <ColumnDefinition Width="{TemplateBinding ListWidth}"/>
                        <ColumnDefinition Width="auto"/>
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>

                    <Border Background="{TemplateBinding BackColor}" Height="{TemplateBinding Height}" BorderThickness="1" BorderBrush="{DynamicResource bordaSuperior}">
                        <!-- link list -->
                        <ListBox x:Name="LinkList" ItemsSource="{Binding Links, RelativeSource={RelativeSource TemplatedParent}}"  
                                             ScrollViewer.HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" >

                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <Grid Height="50" Background="Transparent" Width="500">
                                        <Border Name="border" Padding="10">
                                            <Path x:Name="icon" Data="{Binding IconData}" Stretch="Fill" Fill="{DynamicResource Accent}" Width="20" Height="20" HorizontalAlignment="Left" VerticalAlignment="Center" />
                                        </Border>
                                        <TextBlock x:Name="texto" ToolTip="{Binding Tooltip}"  Text="{Binding DisplayName}" Margin="45,2,2,2" FontSize="{DynamicResource MediumFontSize}" TextTrimming="CharacterEllipsis" VerticalAlignment="Center" HorizontalAlignment="Left" />
                                    </Grid>
                                    <DataTemplate.Triggers>
                                        <DataTrigger Binding="{Binding IconData}" Value="{x:Null}">
                                            <Setter Property="Margin" TargetName="texto">
                                                <Setter.Value>
                                                    <Thickness Bottom="2" Top="2" Left="10" Right="2"/>
                                                </Setter.Value>
                                            </Setter>
                                        </DataTrigger>
                                        <Trigger Property="IsMouseOver" Value="true">
                                            <Trigger.Setters>
                                                <Setter Property="controls:ModernVerticalMenu.BackColor" Value="Red"/>
                                                <Setter Property="Fill" TargetName="icon">
                                                    <Setter.Value>
                                                        <SolidColorBrush Color="#f2f2f2" />
                                                    </Setter.Value>
                                                </Setter>
                                            </Trigger.Setters>
                                        </Trigger>
                                    </DataTemplate.Triggers>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
                    </Border>

                    <Border x:Name="submenu" Grid.Column="1" Background="{DynamicResource background}" Height="{TemplateBinding Height}" BorderThickness="1" BorderBrush="{DynamicResource bordaSuperior}">
                        <!-- link list -->

                        <ListBox x:Name="list" ItemsSource="{Binding SelectedLinkGroup, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"  
                                             ScrollViewer.HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" >

                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <Grid Height="50" Background="Transparent" Width="500">
                                        <Border Padding="10">
                                            <Path x:Name="icon" Data="{Binding IconData}" Stretch="Fill" Fill="{DynamicResource Accent}" Width="20" Height="20" HorizontalAlignment="Left" VerticalAlignment="Center" />
                                        </Border>
                                        <TextBlock x:Name="texto" ToolTip="{Binding Tooltip}"  Text="{Binding DisplayName}" Margin="45,2,2,2" FontSize="{DynamicResource MediumFontSize}" TextTrimming="CharacterEllipsis" VerticalAlignment="Center" HorizontalAlignment="Left" />

                                    </Grid>
                                    <DataTemplate.Triggers>
                                        <DataTrigger Binding="{Binding IconData}" Value="{x:Null}">
                                            <Setter Property="Margin" TargetName="texto">
                                                <Setter.Value>
                                                    <Thickness Bottom="2" Top="2" Left="10" Right="2"/>
                                                </Setter.Value>
                                            </Setter>

                                        </DataTrigger>
                                        <Trigger Property="IsMouseOver" Value="true">
                                            <Setter Property="Fill" TargetName="icon">
                                                <Setter.Value>
                                                    <SolidColorBrush Color="#f2f2f2" />
                                                </Setter.Value>
                                            </Setter>
                                            <!--{Binding RelativeSource={RelativeSource AncestorType=controls:ModernVerticalMenu}, Path=SelectedLinkGroup}-->
                                            <Setter Property="controls:ModernVerticalMenu.SelectedLinkGroup" Value="{Binding Children}"/>
                                        </Trigger>
                                    </DataTemplate.Triggers>
                                </DataTemplate>
                            </ListBox.ItemTemplate>

                        </ListBox>
                    </Border>

                    <controls:ModernFrame Grid.Column="2" Source="{Binding SelectedSource, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" ContentLoader="{TemplateBinding ContentLoader}" Margin="10,0,0,0" />
                </Grid>
                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding SelectedLinkGroup.Count,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}" Value="{x:Null}">
                        <Setter Property="Visibility" TargetName="submenu" Value="Collapsed"/>
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

</Style>

Upvotes: 0

Views: 1253

Answers (1)

sondergard
sondergard

Reputation: 3234

ListBox.Items does not actually contain ListBoxItems, but the underlying object which is being displayed by the ListBoxItem. This is how to get the ListBoxItem:

foreach(var item in linkList.Items)
{
    var container = (ListBoxItem)linkList.ItemsContainerGenerator.ContainerFromItem(item);
}

EDIT:

However, as pushpraj points out, the ListBox is by default virtualized, which means the only the visible items will have a ListBoxItem. Furthermore, once they are scrolled out of view, they are dropped. Therefore attaching an event handler to the ListBoxItem from outside is quite risky because you can easily leak event handlers as ListBoxItems are created and dropped when scrolling.

UPDATE:

Since you specify you own item template you can also just hook up a MouseEnter event on the grid:

<ListBox x:Name="LinkList" ... >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid MouseEnter="OnMouseEnterItem" Height="50" Background="Transparent" Width="500" >
                ...
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Upvotes: 1

Related Questions