【问题标题】:WPF - Hovering over one Element shows content in another ElementWPF - 将鼠标悬停在一个元素上会显示另一个元素中的内容
【发布时间】:2009-04-23 23:25:32
【问题描述】:

我想实现一种效果,我可以将鼠标悬停在按钮上并让 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,但我似乎无法正确连接它。

【问题讨论】:

  • 如果我有误解,请纠正我,但听起来你只是想使用 XAML 来做到这一点?我很确定它不能单独使用 XAML 来完成。如果您使用 ListView 而不是 ItemsControl,您可以将 TextBlock 绑定到 ListView 的 SelectedItem 属性,但这仍然无法解决悬停问题。为此,您将(我认为)需要使用代码隐藏。不过,我不是 WPF 专家。

标签: wpf


【解决方案1】:

我不相信没有一些代码你就能够完成这个......但是,你不需要使用代码隐藏。 “行为”可以很好地解决这个问题(老派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,它处理MouseEnter/MouseLeave 来通知父HoverTrackingItemsControl。这个解决方案可能更容易实现,尽管它确实需要一个专门的控件,而 Behavior 解决方案更通用,可以与任何 ItemsControl 类型(ItemsControl、ListBox、ComboBox 等)一起使用。

【讨论】:

  • 感谢您迄今为止的帮助。我有,但是需要一些额外的帮助来处理附加属性。在 ItemsControl 中的每个项目上连接 MouseEnter/MouseExit 的最佳方法是什么?我可以连接 ItemsComtrol 的事件(而不是每个项目),但这只会在您将鼠标悬停在整个集合上一次时触发 MouseEnter/Exit 事件(除非我在按钮周围添加一些边距)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多