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