触发器中无法识别列表视图中的滚动查看器

本文关键字:滚动 列表 识别 触发器 视图 | 更新日期: 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>

ComputedActual、番茄、土豆。没有人说这必须有意义。

最后也是最糟糕的问题是,ListViewScrollViewer.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 分析器不必尝试猜测它正在查看的内容。