触发器中无法识别列表视图中的滚动查看器
本文关键字:滚动 列表 识别 触发器 视图 | 更新日期: 2023-09-27 17:57:47
在文本块中,我设置了一个触发器来控制文本块的宽度。在触发器中,我想查询列表视图 ListView A 的垂直滚动条是否可见。但是绑定不起作用。"ScrollViewer.VerticalScrollBarVisibility"和"VerticalScrollBarVisibility"均不被接受:"无法解析属性"ScrollViewer"(或"VerticalScrollBarVisibility"(在类型为"System.Windows.Controls.Listview"的数据上下文中。我应该更改什么?
亚历山大
<TextBlock>
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Width" Value="453" />
<Style.Triggers>
<!--Binding-Error!-->
<DataTrigger Binding="{Binding ScrollViewer.VerticalScrollBarVisibility, ElementName=ListViewA}" Value="Visible">
<Setter Property="Width" Value="300" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<ListView x:Name="ListViewA" ScrollViewer.VerticalScrollBarVisibility="Auto" />
我无法在 atm 上测试它,但它应该可以工作,但试试这个
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Width" Value="453" />
<Style.Triggers>
<!--Binding-Error!-->
<DataTrigger Binding="{Binding Path=(ScrollViewer.VerticalScrollBarVisibility), ElementName=ListViewA}" Value="Visible">
<Setter Property="Width" Value="300" />
</DataTrigger>
</Style.Triggers>
</Style>
这是因为 VerticalScrollBarVisibility 是附加属性而不是依赖项属性。
这里有三个问题:
首先,ScrollViewer.*
属性是附加属性。绑定中的Path
意味着TextBlock
具有ScrollViewer
属性,而该属性又具有VerticalScrollBarVisibility
属性,但这根本不是您要表达的内容。 ScrollViewer.
是附加属性名称的一部分,而不是其他属性路径元素。你通过把ClassName.PropertyName
放在参数中来表明这一点:{Binding (ClassName.PropertyName)}
.
其次,ScrollViewer.VerticalScrollBarVisibility
将被Auto
,因为这是您在属性中设置的。如果你想要"live"运行时值,你需要使用不同的属性——就像Width
vs ActualWidth
一样。在这种情况下,ScrollViewer.ComputedVerticalScrollBarVisibility
是您想要的。碰巧该属性无法按你想象的方式工作(这是下面的问题三(,但如果是这样,你的 XAML 将如下所示:
<DataTrigger
Binding="{Binding (ScrollViewer.ComputedVerticalScrollBarVisibility), ElementName=ListViewA}"
Value="Visible"
>
<Setter Property="Width" Value="300" />
<Setter Property="Background" Value="DeepSkyBlue" />
</DataTrigger>
Computed
、Actual
、番茄、土豆。没有人说这必须有意义。
最后也是最糟糕的问题是,ListView
上ScrollViewer.ComputedVerticalScrollBarVisibility
的附加财产是毫无意义的垃圾。它总是返回Visible
.因此,您无法在直接 XAML 中执行此操作。我们必须编写一个值转换器,用于在 ListView 的可视化树中查找实际的ScrollViewer
对象,并返回其属性之一。
public class GetVisualDescendantProperty : MarkupExtension, IValueConverter
{
public DependencyProperty Property { get; set; }
public Type Type { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (value as DependencyObject)
?.GetDescendants()
.Where(d => d.GetType() == Type)
.FirstOrDefault()
?.GetValue(Property);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
public static class Extensions
{
public static IEnumerable<DependencyObject> GetDescendants(this DependencyObject obj)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); ++i)
{
var child = VisualTreeHelper.GetChild(obj, i);
yield return child;
foreach (var descendant in child.GetDescendants())
{
yield return descendant;
}
}
}
}
和 XAML:
<DataTrigger
Binding="{Binding ElementName=ListViewA, Converter={local:GetVisualDescendantProperty Property=ScrollViewer.ComputedVerticalScrollBarVisibility, Type=ScrollViewer}}"
Value="Visible"
>
<Setter Property="Width" Value="300" />
<Setter Property="Background" Value="DeepSkyBlue" />
</DataTrigger>
在MarkupExtension
初始化中,我们不需要Property=ScrollViewer.ComputedVerticalScrollBarVisibility
周围的括号,因为此字符串未被解析为PropertyPath
。由于该属性被声明为 public DependencyProperty Property
,因此 XAML 分析器不必尝试猜测它正在查看的内容。