WPF:如何将ItemsControl.ItemTemplate中的MouseEnter事件绑定到此ItemsControl之外的元素

WPF:如何将ItemsControl.ItemTemplate中的MouseEnter事件绑定到此ItemsControl之外的元素,wpf,binding,itemscontrol,Wpf,Binding,Itemscontrol,我是WPF的新手,但我在写我的第一个严肃项目时进展缓慢。我不确定我使用的术语是否正确,请耐心听我说 我实现了一组ItemsControl(用户控件)。项目源是项目的集合。每个项都包含很多数据,包括它自己的ID。我希望用户控件在鼠标悬停在这组项控件之外的另一个控件上时更改属性。 使事情复杂化的是,另一个控件也是另一个ItemsControl集合的元素 <UserControl x:Class="ClassName" xmlns="http://schemas.mic

我是WPF的新手,但我在写我的第一个严肃项目时进展缓慢。我不确定我使用的术语是否正确,请耐心听我说

我实现了一组ItemsControl(用户控件)。项目源是项目的集合。每个项都包含很多数据,包括它自己的ID。我希望用户控件在鼠标悬停在这组项控件之外的另一个控件上时更改属性。 使事情复杂化的是,另一个控件也是另一个ItemsControl集合的元素

<UserControl x:Class="ClassName"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4">
    <i:Interaction.Triggers>
        <!-- this will call the associated commands on your viewmodel when the mouse enters/leaves the corresponding view in your itemscontrol, from there you can create the viewmodel functionality you'd like-->
        <i:EventTrigger EventName="MouseEnter">
            <i:InvokeCommandAction Command="{Binding MouseEnterCommand}"/>
        </i:EventTrigger>
        <i:EventTrigger EventName="MouseLeave">
            <i:InvokeCommandAction Command="{Binding MouseLeaveCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>

    <Grid Height="10" Width="10">
        <!--the content of your usercontrol-->  
    </Grid>

</UserControl>
我已经设法将悬停控件的ID存储在顶级属性(在顶级DataContext中)中,但是我找不到从DataTemplate中的元素绑定到它的方法

以下是一个屏幕截图:

在本例中,用户将鼠标悬停在通道14上-因此,底部轴X和Z应高亮显示(根据数据库中存储的数据,我任意选择了它们)

如果有任何想法,我将不胜感激。例子将是最受欢迎的

假设: 1) 您正在使用MVVM设计模式。 2) ItemsControl中的每个项都有一个基础ViewModel

然后,您需要处理视图中的MouseEnter和MouseLeave事件,并让它们在视图模型中触发命令。然后让这些ViewModels更新其他ViewModels中的属性,以使它们高亮显示其他items控件中的相应项

<UserControl x:Class="ClassName"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4">
    <i:Interaction.Triggers>
        <!-- this will call the associated commands on your viewmodel when the mouse enters/leaves the corresponding view in your itemscontrol, from there you can create the viewmodel functionality you'd like-->
        <i:EventTrigger EventName="MouseEnter">
            <i:InvokeCommandAction Command="{Binding MouseEnterCommand}"/>
        </i:EventTrigger>
        <i:EventTrigger EventName="MouseLeave">
            <i:InvokeCommandAction Command="{Binding MouseLeaveCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>

    <Grid Height="10" Width="10">
        <!--the content of your usercontrol-->  
    </Grid>

</UserControl>

获得正确的命令后,通知viewmodel鼠标悬停在其上(或离开它)。您可以管理viewmodels的状态,以创建所需的效果

我真的很喜欢这种东西

因为您提到在属性中有悬停ID设置,所以可以从根级别的开始。接下来,您可能希望调用一个命令(而不仅仅是一个方法),因为您的操作包含一个参数(ID)。用于此。可以在视图或视图模型上触发命令。如果要在视图上触发它,那么可能需要使用
ElementName
作为绑定

这里有一个例子

<UserControl>
    <i:Interaction.Triggers>
        <!-- When "SelectedID" changes, invoke the "SelectedIDChangedCommand" on the 
             element "AxesAndButtons".  Pass the value of "SelectedID" as the 
             command parameter -->
        <ei:PropertyChangedTrigger Binding="{Binding SelectedID}">
            <i:InvokeCommandAction CommandParameter="{Binding SelectedID}"
                Command="{Binding ElementName=AxesAndButtons,Path=SelectedIDChangedCommand}" />
        </ei:PropertyChangedTrigger>
    <i:Interaction.Triggers>

    <my:AxesAndButtonsControl x:Name="AxesAndButtons">
    </my:AxesAndButtonsControl>
</UserControl>
Edit我刚刚注意到您可能还没有绑定
MouseOver
事件来更新
SelectedID
属性。如果是这种情况,那么您应该能够使用a和a(在
FindAncestor
ElementName
绑定中)来更新它。大概是这样的:

public class AxesAndButtonsControl : UserControl
{
    public static readonly DependencyProperty SelectedIDChangedCommand = DependencyProperty.Register("SelectedIDChangedCommand", 
        typeof(ICommand), 
        typeof(AxesAndButtonsControl),
        new PropertyMetadata(null));

    public AxesAndButtonsControl()
    {
        SelectedIDChangedCommand = new DelegateCommand(id => {
            // highlight "X" and "Z" or whatever
        });
    }
}
<DataTemplate>
    <Grid>
        <i:Interaction.Triggers>
            <!-- When "MouseEnter" gets triggered, set the property "SelectedID" on the 
                 data context of the closest "UserControl" parent to the value of "ItemID" 
                 in the current data context -->
            <i:EventTrigger EventName="MouseEnter">
                <ei:ChangePropertyAction Value="{Binding ItemID}"
                    TargetObject="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext}"
                    PropertyName="SelectedID" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Grid>
</DataTemplate>


是的,我打算写一些类似的东西。基本上,您需要一种方法来判断所选项目何时从顶部更改。当您可以这样做时,您就可以更新它下面的itemscontrol。您是说不同itemscontrol集合的两个元素之间的交互需要外部包来配合吗?在我看来,如果用户手动控制放置位置,我可以使用多重绑定和转换器。难道不能从驻留在DataTemplate中的控件访问顶级属性吗?请参阅使用内置InvokeCommandAction而不是MVVM Light的EventToCommand更新的示例。感谢您的帮助。事实上,我的目标框架是.NET3.5,所以在合并您的解决方案时遇到了一个问题。此外,我觉得这种方法可能有些过分。毕竟,如果我只能访问顶级数据上下文,我就可以了。所以,在谷歌搜索了很多之后,我发现了一个代理顶级数据上下文的黑客。设置代理对象后,所有控件都可以使用它。所以,链接是如果我得到良好的响应,我将尝试发布一个示例。@Shaul是的,我以前使用过“绑定代理”,这是一种有用的技术。