WPF ListBox 模板绑定仅在滚动时更新
Posted
技术标签:
【中文标题】WPF ListBox 模板绑定仅在滚动时更新【英文标题】:WPF ListBox Template bindings update only on scrolling 【发布时间】:2016-08-20 20:59:10 【问题描述】:我有以下 ListBox,其中 ContentControl 作为 DataTemplate:
<ListBox x:Name="lstActionConfigs" ItemsSource="Binding Path=AllActionConfigList" SelectedItem="Binding Path=ListSelectedItem, Mode=TwoWay" HorizontalContentAlignment="Stretch" Grid.Row="3" Margin="0,0,0,5">
<ListBox.ItemTemplate>
<DataTemplate DataType="x:Type helper:ItemDetails">
<ContentControl Template="StaticResource ResourceKey=actionDetailsListItemTemplate" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<i:Interaction.Behaviors>
<behaviours:BringIntoViewBehaviour CustomIsSelected="Binding Path=IsSelected, Mode=TwoWay"/>
</i:Interaction.Behaviors>
</ContentControl>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
每个有界实例都有 'IsSelected' 属性,通过INotifyPropertyChanged
通知 UI 更改:
public bool IsSelected
get return isSelected;
set
isSelected = value;
notify("IsSelected");
我构建了一个自定义行为,可以查看将其 IsSelectedProperty 更改为 true 的元素,如下所示:
public class BringIntoViewBehaviour : Behavior<FrameworkElement>
public bool CustomIsSelected
get return (bool)GetValue(CustomIsSelectedProperty);
set SetValue(CustomIsSelectedProperty, value);
public static readonly DependencyProperty CustomIsSelectedProperty =
DependencyProperty.Register("CustomIsSelected", typeof(bool), typeof(BringIntoViewBehaviour), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(customIsSelectedPropertyChanged_Callback)));
private static void customIsSelectedPropertyChanged_Callback(DependencyObject o, DependencyPropertyChangedEventArgs e)
BringIntoViewBehaviour thisControl = o as BringIntoViewBehaviour;
if (thisControl == null)
return;
bringIntoView(thisControl);
此项目目前不在 UI 上显示,因为它位于列表底部(有一个滚动条)。
我用true
值更新了IsSelected
属性。
然而,customIsSelectedPropertyChanged_Callback
方法应该在我们更新它的有界属性时执行。
但是,实际上,只有在将滚动条向下移动到 UI 上显示该项目时,才会调用此方法。
【问题讨论】:
【参考方案1】:最有可能的原因是 UI 虚拟化。 ListBox
项目主机默认为 VirtualizingStackPanel
。它不会生成现在看不见的项目,因此当您在模型上设置 IsSelected 时,您的 DataTemplate
以及您的行为尚未创建。只有当您向下滚动时,才会与数据模板中的行为一起创建控件,并在绑定后将CustomIsSelectedProperty
设置为true,因此会调用您的回调。
要验证此假设,您可以为您的 ListBox
禁用 UI 虚拟化,看看是否可以解决问题。
【讨论】:
我禁用了 UI 可视化,正如你所说的 ,现在它可以完美运行了。非常感谢! 不客气。确保您了解禁用虚拟化的含义,尤其是当您期望该 ListBox 中有很多项目时。以上是关于WPF ListBox 模板绑定仅在滚动时更新的主要内容,如果未能解决你的问题,请参考以下文章
WPF ListBox 未使用 ItemsSource 更新
WPF ListBox/ListView/DataGrid 列表滚动与虚拟化