4

我尝试{RelativeSource PreviousData}在 a中使用ListBox.ItemTemplate,它工作正常。

但是,当使用下面提供的特定代码时,绑定会在向上向下滚动几次时停止工作,并且缺少一些s。Rectangle

该问题即使在使用单个时也会重现DataTrigger,但在超过178时不会重建。ListBox.Height

示例 GIF - 缺少绿线!:

常规滚动有效,但快速滚动会导致它绑定到“松动”


MainWindow.Xaml 源代码:

<Window
    x:Class="PreviousDataBindingWheelIssue.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:PreviousDataBindingWheelIssue"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="PreviousData Issue"
    d:DataContext="{d:DesignInstance Type=local:MyModel}"
    SizeToContent="WidthAndHeight"
    mc:Ignorable="d">
    <StackPanel>

        <!--  Height must be less or equal to 178  -->
        <ListBox
            Width="300"
            Height="178"
            HorizontalContentAlignment="Stretch"
            ItemsSource="{Binding MyData}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <DockPanel Background="#FFFFFFED">
                        <Rectangle
                            Height="2"
                            Margin="0"
                            DockPanel.Dock="Top">
                            <Rectangle.Style>
                                <Style TargetType="Rectangle">
                                    <Setter Property="Fill" Value="#FF63605C" />
                                    <Style.Triggers>

                                        <!--
                                            Hide our magnificent separator if this is the first item on the list
                                            see http://stackoverflow.com/a/22705507/426315
                                            but, it seems to have some issues when using mouse wheel
                                            some of the rows does NOT have the rectangle even when PreviousData SHOULD not be null
                                        -->
                                        <DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
                                            <Setter Property="Visibility" Value="Collapsed" />
                                        </DataTrigger>

                                        <DataTrigger Binding="{Binding}" Value="Fun Item">
                                            <Setter Property="Fill" Value="SpringGreen" />
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </Rectangle.Style>
                        </Rectangle>

                        <TextBlock
                            Margin="5,7,5,7"
                            VerticalAlignment="Center"
                            FontSize="12"
                            Text="{Binding}" />
                    </DockPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </StackPanel>
</Window>

后面的主窗口代码:

using System.Windows;
namespace PreviousDataBindingWheelIssue
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MyModel();
        }
    }
}

MyModel.cs 来源:

using System.Collections.ObjectModel;

namespace PreviousDataBindingWheelIssue
{
    public class MyModel
    {
        public ObservableCollection<string> MyData { get; set; }

        public MyModel()
        {
            MyData = new ObservableCollection<string>()
            {
                "Lorem ipsum dolor", "sit amet, consectetur", "adipiscing elit. Sed",
                "Fun Item",
                "rhoncus leo convallis", "pulvinar tellus at",
                "Fun Item",
                "porta metus. Mauris", "sed mauris quis", "neque congue semper",
                "Fun Item",
                "vitae non leo", "Donec aliquet feugiat", "massa vitae luctus",
                "Fun Item",
                "Duis pharetra velit", "et lorem blandit"
            };
        }
    }
}
4

1 回答 1

2

由于PreviousData绑定与虚拟化不可靠,您可以通过设置禁用虚拟化VirtualizingPanel.IsVirtualizing="False"ListBox或者使绑定虚拟化准备就绪。

处理此类问题的一种方法是创建一个自定义列表框(ListBox2在我的示例代码中),覆盖PrepareContainerForItemOverride并设置一些可用于进一步操作的属性。ItemIndex为此,我创建了一个附加属性。

public class ListBox2 : ListBox
{
    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        base.PrepareContainerForItemOverride(element, item);
        SetItemIndex(element, ItemContainerGenerator.IndexFromContainer(element));
    }


    // helper attached property to indicate the index of listbox items

    public static int GetItemIndex(DependencyObject obj)
    {
        return (int)obj.GetValue(ItemIndexProperty);
    }

    protected static void SetItemIndex(DependencyObject obj, int value)
    {
        obj.SetValue(ItemIndexPropertyKey, value);
    }

    private static readonly DependencyPropertyKey ItemIndexPropertyKey =
        DependencyProperty.RegisterAttachedReadOnly("ItemIndex", typeof(int), typeof(ListBox2), new PropertyMetadata(-1));

    public static readonly DependencyProperty ItemIndexProperty = ItemIndexPropertyKey.DependencyProperty;
}

然后将 xaml 更改为使用ListBox2并依赖于,ItemIndex而不是PreviousData

<local:ListBox2
    Width="300"
    Height="178"
    HorizontalContentAlignment="Stretch"
    ItemsSource="{Binding MyData}">
    <local:ListBox2.ItemTemplate>
        <DataTemplate>
            <DockPanel Background="#FFFFFFED">
                <Rectangle
                    Height="2"
                    Margin="0"
                    DockPanel.Dock="Top">
                    <Rectangle.Style>
                        <Style TargetType="Rectangle">
                            <Setter Property="Fill" Value="#FF63605C" />
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Path=(local:ListBox2.ItemIndex),RelativeSource={RelativeSource AncestorType=ListBoxItem}}" Value="0">
                                    <Setter Property="Visibility" Value="Collapsed" />
                                </DataTrigger>

                                <DataTrigger Binding="{Binding}" Value="Fun Item">
                                    <Setter Property="Fill" Value="SpringGreen" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Rectangle.Style>
                </Rectangle>

                <TextBlock
                    Margin="5,7,5,7"
                    VerticalAlignment="Center"
                    FontSize="12"
                    Text="{Binding}" />
            </DockPanel>
        </DataTemplate>
    </local:ListBox2.ItemTemplate>
</local:ListBox2>
于 2017-08-23T13:31:56.063 回答