WPF - 将鼠标悬停在一个元素上可显示另一个元素中的内容

时间:2009-04-23 23:25:33

标签: wpf

我想实现一种效果,我可以将鼠标悬停在Button上并让TextBlock更新其内容(通过绑定)。更复杂的是,Button是ItemsControl / DataTemplate中定义的众多按钮之一。 TextBlock超出了ItemsControl的范围。

问题的一些简化标记如下:

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>
  <ItemsControl Grid.Row="0">
    <ItemsControl.ItemTemplate>
      <DataTemplate>
        <Button Content="{Binding Title}"
                Command="{Binding Command}" />    
      </DataTemplate>
    </ItemsControl.ItemTemplate>
  </ItemsControl>
  <TextBlock x:Name="TitleTextBox" Grid.Row="1" />
</Grid>

在这个例子中,我可能希望将数据项的“Title”属性绑定到TextBlock的“Text”属性。

我想我想要点击按钮的IsMouseOver,但我似乎无法正确地连接它。

1 个答案:

答案 0 :(得分:4)

我不相信你没有一些代码就能完成这个......但是,你不需要使用代码隐藏。 “行为”对此可以正常工作(旧学校attached behavior或更现代Blend Behavior)。以下是使用附加行为修改的标记的外观:

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>
  <ItemsControl x:Name="Buttons" Grid.Row="0" ext:Hover.TrackChildItems="true">
    <ItemsControl.ItemTemplate>
      <DataTemplate>
        <Button Content="{Binding Title}"
                Command="{Binding Command}" />
      </DataTemplate>
    </ItemsControl.ItemTemplate>
  </ItemsControl>
  <TextBlock x:Name="TitleTextBox"
             Grid.Row="1"
             Text="{Binding ElementName=Buttons, Path=ext:Hover.Item.Content}" />
</Grid>

此处附加的行为“Hover.TrackChildItems”用于监视适当的鼠标事件,并将只读“Hover.Item”附加属性设置为悬停在其上的控件。编写行为应该很简单,留给你。

编辑:要设置项目的事件处理程序,首先要做的事情很简单明了:迭代Items属性中的项目并添加处理程序。

Mouse.AddMouseEnter(item, OnMouseEnter);

这适用于静态内容,但动态(在运行时添加和删除)内容将被此错过。因此,接下来您必须跟踪Items属性的更改。

((INotifyCollectionChanged)Items).CollectionChanged += OnItemsChanged;

在CollectionChanged处理程序中添加和删除项目时,根据需要添加或删除鼠标事件处理程序。

还有另一种解决方案。为此创建一个新的HoverTrackingItemsControl,派生自ItemsControl。在此控件中,重写GetContainerForItemOverride方法以返回新的HoverTrackingItem,该HoverTrackingItem处理MouseEnter / MouseLeave以通知父HoverTrackingItemsControl。此解决方案可能更容易实现,但它确实需要专门的控件,而行为解决方案更通用,可以与任何ItemsControl类型(ItemsControl,ListBox,ComboBox等)一起使用。