none
后台线程更新数据源,UI无法正确显示。 RRS feed

  • 问题

  • listview绑定到数据源 messageCollection,

    Binding binding = new Binding();
    binding.Source = messageCollection;
    binding.Mode = BindingMode.OneWay;
    listview.SetBinding(ListView.ItemsSourceProperty, binding);

    由后台线程向messageCollection添加Item,

     public void MessageRecieveCallback(string message)
     {
                IAsyncAction ThreadPoolWorkItem = Windows.System.Threading.ThreadPool.RunAsync
                    (new WorkItemHandler(
                        (IAsyncAction source) =>
                        {
                            ThisDispatcher.InvokeAsync(CoreDispatcherPriority.Normal,
                            (sender, args) =>
                            {
                                messageCollection.Add(message);

                                listScrollViewer.ScrollToVerticalOffset(listScrollViewer.ExtentHeight);

                            },
                            source,
                            null);
                        }
                    ));   }

    listScrollViewer 是listview的ScrollViewer

    现在问题是:当接收到新信息时,listview能够显示出新添加的message,但listScrollViewer 不能滚动到最低部,只能滚动到listview的倒数第2个item.

    有什么方法可以解决这个问题吗!!怀疑产生此问题的原因是在执行listScrollViewer.ScrollToVerticalOffset方法时,新添加的message还没有加载到UI。

     

    2012年5月8日 8:14

答案

  • 你不要在ItemContainerGenerator_ItemsChanged事件中

    public void MessageRecieveCallback(string message) { IAsyncAction ThreadPoolWorkItem = Windows.System.Threading.ThreadPool.RunAsync (new WorkItemHandler( (IAsyncAction source) => { ThisDispatcher.InvokeAsync(CoreDispatcherPriority.Normal, (sender, args) => { messageCollection.Add(message);

    listScrollViewer.UpdateLayout();//在这里 listScrollViewer.ScrollToVerticalOffset(listScrollViewer.ExtentHeight); }, source, null); } )); }


    • 已标记为答案 edmundzhang 2012年5月11日 10:20
    2012年5月11日 9:50

全部回复

  • 你试试  Windows::UI::Xaml::Controls::ScrollViewer::InvalidateScrollInfo()
    2012年5月9日 5:02
  • 你可以在 listview 的

    ItemContainerGenerator.ItemsChanged 

    事件中去做,这样能够保证在Item添加后,再去控制滚动:

    listview.ItemContainerGenerator.ItemsChanged += ItemContainerGenerator_ItemsChanged;
    ...
    void ItemContainerGenerator_ItemsChanged(object sender, ItemsChangedEventArgs e)
    {
        listScrollViewer.ScrollToVerticalOffset(listScrollViewer.ExtentHeight);
    }


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年5月9日 5:27
    版主
  • 使用了您的方法,但是产生的结果没有发生变化,listScrollViewer 还是只能滚动到listview的倒数第2个item.

    2012年5月9日 7:45
  • 那么

    void ItemContainerGenerator_ItemsChanged(object sender, ItemsChangedEventArgs e)
    {
      int count = listview.Items.Count - 1;
      listview.SelectedIndex = count;
      listview.ScrollIntoView(listview.SelectedItem);
    }

    可以吗? 


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年5月9日 10:34
    版主
  • 那么

    void ItemContainerGenerator_ItemsChanged(object sender, ItemsChangedEventArgs e)
    {
      int count = listview.Items.Count - 1;
      listview.SelectedIndex = count;
      listview.ScrollIntoView(listview.SelectedItem);
    }

    可以吗? 


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    这样也不可以,而且滚动条都不滚动。修改了方法,监视变量,如下变化

     private void ItemContainerGenerator_ItemsChanged(object sender, ItemsChangedEventArgs e)
            {  //listview有10条Item
                int count = listview.Items.Count - 1;(listview.Items.Count =10)
                //listview.SelectedIndex = count;
                //listview.ScrollIntoView(ChatListView.SelectedItem);
                ScrollViewer scrollviewer = GetVisualChild<ScrollViewer>(listview);
                if (scrollviewer != null)
                {
                    scrollviewer.ScrollToVerticalOffset(scrollviewer.ExtentHeight ); scrollviewer.ExtentHeight =9
                }

            }

    scrollviewer.ExtentHeight 总是比实现Item小于1。

    2012年5月11日 3:36
  • 加一句scrollviewer.UpdateLayout();就可以了。如下:

    ScrollViewer scrollviewer = GetVisualChild<ScrollViewer>(listview); if (scrollviewer != null) {

    scrollviewer.UpdateLayout(); scrollviewer.ScrollToVerticalOffset(scrollviewer.ExtentHeight );

    scrollviewer.ExtentHeight =9 }



    2012年5月11日 6:02
  • 加一句scrollviewer.UpdateLayout();就可以了。如下:

    ScrollViewer scrollviewer = GetVisualChild<ScrollViewer>(listview); if (scrollviewer != null) {

    scrollviewer.UpdateLayout(); scrollviewer.ScrollToVerticalOffset(scrollviewer.ExtentHeight );

    scrollviewer.ExtentHeight =9 }



    可以吗?我怎么试着不行呢!!
    2012年5月11日 7:52
  • 你不要在ItemContainerGenerator_ItemsChanged事件中

    public void MessageRecieveCallback(string message) { IAsyncAction ThreadPoolWorkItem = Windows.System.Threading.ThreadPool.RunAsync (new WorkItemHandler( (IAsyncAction source) => { ThisDispatcher.InvokeAsync(CoreDispatcherPriority.Normal, (sender, args) => { messageCollection.Add(message);

    listScrollViewer.UpdateLayout();//在这里 listScrollViewer.ScrollToVerticalOffset(listScrollViewer.ExtentHeight); }, source, null); } )); }


    • 已标记为答案 edmundzhang 2012年5月11日 10:20
    2012年5月11日 9:50
  • 问题解决了!!这是为什么呢!!

    2012年5月11日 10:20