WPF ListBox模板绑定仅在滚动时更新

时间:2016-04-26 20:19:37

标签: c# wpf mvvm data-binding listbox

我有以下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>

每个有界实例都有&#39; IsSelected&#39;通过INotifyPropertyChanged

通知用户更改的属性
public bool IsSelected
{
    get { return isSelected; }
    set
    {
        isSelected = value;
        notify("IsSelected");
    }
}

我构建了一个自定义行为,用于查看将其更改为IsSelectedProperty的元素,如下所示:

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上,因为它位于列表底部(有一个滚动条)。

我使用IsSelected值更新了true属性。

但是,我们应该更新它的有界属性时执行customIsSelectedPropertyChanged_Callback方法。

但是,实际上,只有在将滚动条向下移动到UI上时,才会调用此项目。

1 个答案:

答案 0 :(得分:5)

最有可能的原因是UI虚拟化。 ListBox项主机默认为VirtualizingStackPanel。它不会生成现在不可见的项目,因此当您在模型上设置IsSelected时,您的DataTemplate以及您的行为尚未创建。只有向下滚动时,控件才会与数据模板中的行为一起创建,绑定后CustomIsSelectedProperty设置为true,因此调用回调。

要验证此假设,您可以停用ListBox的UI虚拟化,看看是否能解决问题。