如何在Code Behind上的ListBox中添加鼠标的事件

时间:2014-09-09 13:42:39

标签: c# wpf xaml

private ListBox linkList = new ListBox();

这里我想为linkList

中的每个项添加mouseOver事件

我试过了:

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

但没有奏效 我该怎么办?

这就是ListBox的填充方式:

<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>

更新

代码背后:

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); }
    }
}

由于基类(ResourceDictionary和Control)

的冲突,这会导致编译错误

所有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>

1 个答案:

答案 0 :(得分:0)

ListBox.Items实际上并不包含ListBoxItems,而是由ListBoxItem显示的底层对象。这是获取ListBoxItem的方法:

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

编辑:

但是,正如pushpraj所指出的那样,ListBox默认是虚拟化的,这意味着唯一可见的项目将具有ListBoxItem。此外,一旦它们滚动出视图,它们就会被丢弃。因此,从外部将事件处理程序附加到ListBoxItem是非常危险的,因为在滚动时创建和删除ListBoxItems时,您可以轻松泄漏事件处理程序。

更新:

由于您指定了自己的项目模板,因此您还可以在网格上连接MouseEnter事件:

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