我尝试使用 {RelativeSource PreviousData}
在 ListBox.ItemTemplate
它工作正常。
但是,当使用下面提供的特定代码时,绑定(bind)会在向上向下滚动几次和 时停止工作。一些的Rectangle
s 不见了。
即使使用单个 DataTrigger
也会重现此问题, 但它确实 不是 重构时ListBox.Height
超过 178 .
示例 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"
};
}
}
}
最佳答案
由于PreviousData
绑定(bind)与虚拟化不可靠,您可以通过设置 VirtualizingPanel.IsVirtualizing="False"
禁用虚拟化在 ListBox
,或者让您的绑定(bind)虚拟化准备就绪。
处理此类问题的一种方法是创建自定义列表框(在我的示例代码中为 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>
关于wpf - 绑定(bind) {RelativeSource PreviousData} 在特定情况下会中断绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44005571/