![](/img/trans.png)
[英]WPF: Use PriorityBinding for DisplayMemberBinding in GridViewColumn
[英]WPF - Adding a Tooltip to a GridViewColumn with DisplayMemberBinding
我在需要DisplayMemberBinding
的GridViewColumn
中有一个TextBlock
。 TextBlock
完全没有考虑,因为DisplayMemberBinding
优先于CellTemplate
。 但是, Textblock
有一个ToolTip
,我希望显示它特定于列本身。 我能够将大多数样式设置移到CellTemplate
之外,因为它们对所有列都是通用的,但是ToolTip
不能被带到外面,因为它需要绑定并且对于每列都是唯一的。
这是其中的一列。 由于DisplayMemberBinding
优先, GridViewColumn.CellTemplate
标记中的所有内容都可以删除。
<GridViewColumn Header="Templates"
Width="200"
DisplayMemberBinding="{Binding Path=Name}>
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type request:ModelDocument}">
<TextBlock ToolTip="{Binding Name}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
我完成其他 Style 属性的方式如下。 这是在GridView
之前完成的( GridView
是ListView
的子项):
<ListView.Resources>
<Style TargetType="TextBlock">
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="FontFamily" Value="Segue UI Light" />
<Setter Property="FontSize" Value="13" />
</Style>
</ListView.Resources>
如何在不删除DisplayMemberBinding
的情况下向每列添加唯一的ToolTip
?
正如@icebat 在评论中已经建议的那样, DataGrid
更适合这种情况,为了澄清,这里有一个简单的演示实现:
<DataGrid ItemsSource="{Binding Collection}" AutoGenerateColumns="False">
<DataGrid.Resources>
<Style TargetType="TextBlock" x:Key="TbStyle">
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="FontFamily" Value="Segue UI Light" />
<Setter Property="FontSize" Value="13" />
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Templates" SortMemberPath="Name"
Width="200" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate >
<TextBlock Style="{StaticResource TbStyle}" ToolTip="{Binding Name}" Text="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
尽管有更合适的解决方案,例如使用DataGrid
而不是ListView
,但我想展示一个答案,让您可以在TextBlocks
上使用ListView
、 DisplayMemberBinding
和ToolTip
完全按照您的意愿行事。
最后我有以下XAML:
<ListView ItemsSource="{Binding MyList}">
<ListView.Resources>
<local:GridRowPresenterToDataContextPropertiesConverter x:Key="GridRowPresenterToDataContextPropertiesConverter"></local:GridRowPresenterToDataContextPropertiesConverter>
<Style TargetType="TextBlock">
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="FontFamily" Value="Segue UI Light" />
<Setter Property="FontSize" Value="13" />
<!--THIS IS THE NEW PART-->
<Setter Property="ToolTip">
<Setter.Value>
<MultiBinding Converter="{StaticResource GridRowPresenterToDataContextPropertiesConverter}"
ConverterParameter="Name, Value">
<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=GridViewRowPresenter}"/>
<Binding RelativeSource="{RelativeSource Mode=Self}"/>
</MultiBinding>
</Setter.Value>
</Setter>
<!--END OF THE NEW PART-->
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="Templates" Width="200" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Templates" Width="200" DisplayMemberBinding="{Binding Value}"/>
</GridView>
</ListView.View>
</ListView>
我添加了一个简单的视图 model class 和另一个GridViewColumn
用于测试目的:
public class MyViewModel {
public string Name { get; set; } = "Hello.";
public string Value { get; set; } = "world.";
}
此 XAML 将DataContext
的Name
属性设置为第一列中所有TextBlocks
的ToolTip
,并将DataContext
的Value
属性设置为第二列中所有TextBlocks
的ToolTip
。 您可以通过添加到ConverterParameter="Name, Value"
有序属性列表来处理其他列。
关键在于GridRowPresenterToDataContextPropertiesConverter
的定义(这是我可能写过的最不直接和最老套的IMultiValueConverter
之一):
public class GridRowPresenterToDataContextPropertiesConverter : IMultiValueConverter {
public static T FindVisualSelfOrChildren<T>(DependencyObject parent) where T : DependencyObject {
if (parent == null) return null;
if (parent is T) return parent as T;
IEnumerable<DependencyObject> children = Enumerable.Range(0, VisualTreeHelper.GetChildrenCount(parent)).Select(i => VisualTreeHelper.GetChild(parent, i));
foreach (var child in children) {
T result = FindVisualSelfOrChildren<T>(child);
if (result != null) return result as T;
}
return null;
}
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
var presenter = (GridViewRowPresenter)values[0];
var targetElement = values[1] as FrameworkElement;
var sourceProperties = ((string)parameter).Split(',');
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(presenter); i++) {
var child = VisualTreeHelper.GetChild(presenter, i);
if (FindVisualSelfOrChildren<TextBlock>(child) == targetElement) {
var dataContext = targetElement.DataContext;
return dataContext.GetType().GetProperty(sourceProperties[i].Trim()).GetValue(dataContext);
}
}
return "";
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException();
}
该转换器获取目标元素(这里,它将是每个TextBlock
),找出GridView
的哪一列是存在的,并从ConverterParameter
中提取正确索引处的属性。
这个答案是为了好玩而不是在生产代码中使用,它需要一些更智能的代码来处理现在绝对不支持的列的重新排序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.