简体   繁体   English

在 WPF 中显示鼠标悬停在 DataGridRow 上的控件

[英]Show a control on DataGridRow Mouse Over in WPF

It would be very convenient to show data of a specific item only when the user hovers its row in a static DataGrid.只有当用户将鼠标悬停在 static DataGrid 中的行时,才显示特定项目的数据会非常方便。 What I tried yet is: link MouseEnter and MouseLeave events to methods that will save the Index of the currently Hovered item, create a converter that will compare if the item index is the hovered item index (if yes show, otherwise hide) , and finally call static INPC on the static DataGrid ItemSource, but it seems I am still missing something.我尝试过的是:将 MouseEnter 和 MouseLeave 事件链接到将保存当前悬停项目索引的方法,创建一个转换器来比较项目索引是否是悬停项目索引(如果是则显示,否则隐藏) ,最后在 static DataGrid ItemSource 上调用 static INPC,但似乎我仍然遗漏了一些东西。 (I'm coding in MVVM pattern but since this is strictly View-oriented I have no problem if the solution involves code-behind) (我在 MVVM 模式中编码,但由于这是严格面向视图的,所以如果解决方案涉及代码隐藏,我没有问题)

tl;dr: I wanna achieve this: tl;dr:我想实现这个:

在此处输入图像描述

Here's the full code of what I did yet for easy testing:这是我为方便测试所做的完整代码:

  • View看法
<Window x:Class="MouseOverDataGridRow.MainWindow" 
        [...] >

    <!-- Converter Section -->
    <Window.Resources>
        <local:HoveredRowToVisibilityConverter x:Key="HoveredRowToVisibility"/>
    </Window.Resources>

    <Grid>
        <DataGrid ItemsSource="{Binding MyList, UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False" CanUserAddRows="False">

            <!-- Events Section -->
            <DataGrid.ItemContainerStyle>
                <Style TargetType="{x:Type DataGridRow}">
                    <EventSetter Event="MouseEnter" Handler="DataGridRow_MouseEnter" />
                    <EventSetter Event="MouseLeave" Handler="DataGridRow_MouseLeave" />
                </Style>
            </DataGrid.ItemContainerStyle>

            <!-- Always Visible Data -->
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

                <!-- On Mouse Over Only Data -->
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="Hidden Data" Visibility="{Binding Converter={StaticResource HoveredRowToVisibility}, UpdateSourceTrigger=PropertyChanged}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>

        </DataGrid>
    </Grid>
</Window>
  • Code-behind:代码隐藏:
public partial class MainWindow : Window
{
    // Static INPC (maybe is the problem?)
    public static event PropertyChangedEventHandler StaticPropertyChanged;
    private static void NotifyStaticPropertyChanged([CallerMemberName] string name = null)
    {
        StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(name));
    }

    // Hovered Row Index
    public static int HoveredRowID { get; set; } = -1;

    // DataGrid's ItemSource
    private static ObservableCollection<int> _myList = new ObservableCollection<int>() { 1, 2, 3, 4, 5 };
    public static ObservableCollection<int> MyList
    {
        get { return _myList; }
        set { _myList = value;
            NotifyStaticPropertyChanged();
        }
    }

    // Constructor
    public MainWindow()
    {
        DataContext = this;
        InitializeComponent();            
    }        
    
    // Method that retrieves the id of the Hovered Row and calls INPC. The retrieving part is working, but the View isn't updating
    private void DataGridRow_MouseEnter(object sender, MouseEventArgs e)
    {
        DataGridRow row = (DataGridRow)sender;

        if (row.Item is int)
        {
            int item = (int)row.Item;
            HoveredRowID = MyList.IndexOf(item);
            NotifyStaticPropertyChanged("MyList");
        }

    }

    // Method that resests the Hovered Row and call INPC to hide the previously shown stuff
    private void DataGridRow_MouseLeave(object sender, MouseEventArgs e)
    {
        HoveredRowID = -1;
        NotifyStaticPropertyChanged("MyList");
    }
}

// The converter
public class HoveredRowToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is int)
        {
            int item = (int)value;

            // Check if this item is the hovered item
            if (MainWindow.MyList.IndexOf(item) == MainWindow.HoveredRowID)
                return Visibility.Visible;
            else
                return Visibility.Hidden;
        }
        else
            return Visibility.Hidden;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

@Mitch's instructions are correct, Binding Button.Visibility To DataGridRow 's IsMouseOver is the solution. @Mitch 的说明是正确的,Binding Button.Visibility To DataGridRowIsMouseOver是解决方案。 However an important detail to be able to do that is to use a DataTrigger to do the Binding, and set the default Visbility to Hidden / Collapsed .然而,能够做到这一点的一个重要细节是使用DataTrigger进行绑定,并将默认的Visbility设置为Hidden / Collapsed Here I used DataTemplate.Triggers but it can also be done in Button.Triggers这里我使用了DataTemplate.Triggers但它也可以在Button.Triggers中完成

<DataTemplate>
    <Button x:Name="HiddenDeleteButton" Text="Delete" Visibility="Hidden" />
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource AncestorType=DataGridRow}}" Value="True">
            <Setter Property="Visibility" TargetName="HiddenDeleteButton" Value="Visible"/>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

I think you can just bind Button.Visibility to IsMouseOver on DataGridRow .我认为您可以将Button.Visibility绑定到DataGridRow上的IsMouseOver I don't think there is any need to get fancy (or have anything in code behind).我认为没有必要花哨(或在代码中隐藏任何内容)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM