显示ListBox中的最后一项

时间:2014-04-04 17:05:20

标签: wpf listview .net-4.5

我有一个以XAML定义的绑定listBox

<ListBox ItemsSource="{Binding Messages}" ItemTemplateSelector="{StaticResource lc_messageTemplateSelector}"
          ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalContentAlignment="Stretch" 
         SelectedItem="{Binding SelectedMessage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
         IsSynchronizedWithCurrentItem="True" VirtualizingPanel.ScrollUnit="Pixel" Background="White"
         ItemContainerStyle="{StaticResource NakedListBoxItem}">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel VerticalAlignment="Bottom" />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    <ListBox.Resources>
    </ListBox.Resources>
    <i:Interaction.Behaviors>
        <classes:ScrollIntoViewBehavior />
    </i:Interaction.Behaviors>

我确实向web服务发出请求以获取所需的记录并填写Messages - ObservableCollection,所有项目都会根据需要显示,我遇到的问题是,在我加载所有项目后,我需要使其显示最后一个一。 所以我设置它

SelectedMessage = Messages.Last();

默认情况下,这并不能使用数据绑定,所以我创建了(在SO上找到)这个行为

public sealed class ScrollIntoViewBehavior : Behavior<ListBox>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.SelectionChanged += ScrollIntoView;
        }

        protected override void OnDetaching()
        {
            AssociatedObject.SelectionChanged -= ScrollIntoView;
            base.OnDetaching();
        }

        private static void ScrollIntoView(object o, SelectionChangedEventArgs e)
        {
            Selector selector = o as Selector;
            if (selector is ListBox)
            {
                (selector as ListBox).ScrollIntoView(selector.SelectedItem);
            }
        }
    }

但这不起作用。

这里可能有什么问题以及如何使用数据绑定使其工作。

是否可能是因为某些项目具有复杂的DataTemplate,其中的Image控件以异步模式加载图像并更改ListBox的大小,然后滚动操作错误?

我看到的是,有时它会显示最后一个元素,有时它会滚动到一个随机元素,当它以正确的方式工作时找不到关系。

THX

1 个答案:

答案 0 :(得分:0)

<ScollViewer x:Name="scroller">
    <ListBox x:Name="listbox" SelectionChanged="selectionChanged"   
             ScrollViewer.VerticalScrollBarVisibility="Disabled"/>
</ScrollViewer>`

然后你有代码隐藏

private void selectionChanged(object sender, SelectionChangedEventArgs args)
{
        var container = listbox.ItemContainerGenerator.ContainerFromIndex(listbox.SelectedIndex) as FrameworkElement;
        if (container == null) return;
        var transform = container.TransformToVisual(scroller);
        var elementLocation = transform.Transform(new Point(0, 0));
        double newVerticalOffset = elementLocation.Y + scroller.VerticalOffset;
        scroller.ScrollToVerticalOffset(newVerticalOffset);
}