当且仅当它位于 ListView 的最后一个 ListViewItem(行)中时,才折叠 WPF 按钮

Collapse an WPF button if and only if this is in the last ListViewItem (row) from the ListView

在 WPF ListView 中,我有 3 列 (GridViewColumns)。第一列是自动递增的(1、2、3 等等)。第二个只是一个字符串,最后一列包含 3 个按钮,删除、上移和下移(都在同一列中)。重点说一下我感兴趣的最后一个吧。

我想达到什么目的

我想折叠 ListView 第一行的向上移动按钮(向上箭头),并折叠 ListView 最后一行的向下移动按钮(向下箭头)。对我来说,第一行是从 1 开始的。见下图。

我做了什么? 我对按钮应用了一种样式以折叠第一行中的上移按钮并且它有效,但现在我不知道如何对最后一行中的下移按钮执行相同的操作(请参阅标有红色圆圈的按钮上图)。

这是我的代码:

<Style x:Key="myButtonStyle" TargetType="Button">
    <Style.Triggers>
        <!-- Collapse move up button from the first row of the ListView -->
        <DataTrigger Binding="{Binding (ItemsControl.AlternationIndex),
                                   RelativeSource={RelativeSource AncestorType=ListViewItem}}" Value="1">
            <Setter Property="Visibility" Value="Collapsed"/>
        </DataTrigger>

        <!-- HOWTO: Collapse move down button from the last row of the ListView here??? -->

    </Style.Triggers>
</Style>

正如您在上面看到的,我使用 ItemsControl.AlternationIndex 来为 ListView 的第一列编号。

您需要做的是将当前交替索引与交替计数进行比较。如果 Index == Alternation Count - 1 那么它是最后一行,您可以隐藏该按钮。但是,Value property of DataTrigger 不是依赖项 属性,因此您不能将交替计数绑定为值。此外,您需要将交替计数减去一个与交替指数进行比较。

您可以做的是使用 MultiBinding 绑定交替索引和交替计数。然后您可以创建一个自定义值转换器来检查上述条件和 returns truefalse。作为 DataTriggerValue,您只需分配 True.

让我们创建转换器,returns 如果有两个值相差一个。你可以使它不那么抽象,但这样你绑定索引和计数的顺序并不重要。

public class OffByOneToBoolConverter : IMultiValueConverter
{
   public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
   {
      if (values == null || values.Length != 2 || !(values[0] is int value1) || !(values[1] is int value2))
         return Binding.DoNothing;

      return Math.Abs(value1 - value2) == 1;
   }

   public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
   {
      throw new InvalidOperationException();
   }
}

对于向下按钮,使用 MultiBinding 创建新样式。

<Style x:Key="myDownButtonStyle" TargetType="Button">
   <Style.Triggers>
      <DataTrigger Value="True">
         <DataTrigger.Binding>
            <MultiBinding Converter="{StaticResource OffByOneToBoolConverter}">
               <Binding Path="(ItemsControl.AlternationIndex)"
                        RelativeSource="{RelativeSource AncestorType=ListViewItem}"/>
               <Binding Path="(ItemsControl.AlternationCount)" RelativeSource="{RelativeSource AncestorType={x:Type ListView}}"/>
            </MultiBinding>
         </DataTrigger.Binding>
         <Setter Property="Visibility" Value="Collapsed"/>
      </DataTrigger>
   </Style.Triggers>
</Style>

不要忘记在范围内的任何资源字典中创建 OffByOneToBoolConverter 的实例。顺便说一下,UpDown 按钮需要单独的按钮样式,因为它们都有排他性条件。对于 Up 按钮,请考虑将 Visibility 设置为 Hidden,然后即使 Up按钮未显示。