[英]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:这是我为方便测试所做的完整代码:
<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>
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 DataGridRow
的IsMouseOver
是解决方案。 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.