Force redraw on ListView in windows store app

六月ゝ 毕业季﹏ 提交于 2019-12-11 22:06:05

问题


I am using @Romasz 's answer from Alternating Colors of rows in ListView in Windows Phone 8.1 to give alternate background to ListView items. I change it in order to highlight the selected item, like this:

<local:AlternateConverter CurrentList="{Binding ElementName=myList, Path=ItemsSource}" 
                          HighlightIndex="{Binding ElementName=myList, Path=SelectedIndex}"
                          x:Key="AlternateConverter"/>

Note: I removed the AlternateBrushes property as I only need static colors and add in HighlightItem property binding to the list's selected index.

Then I changed the converter class AlternateConverter appropriately as follow: [NB: this is C++ counterpart.]

Object^ AlternateConverter::Convert(Object^ value, TypeName targetType, Object^ parameter, String^ language)
{
    auto list = reinterpret_cast<IVector<Object^>^>(CurrentList);
    unsigned int i;
    bool r = list->IndexOf(value, &i);

    // This is added to highlight the selected item with a different color
    if (i == HighlightIndex)
        return BrushHighlight;

    return i % 2 == 0 ? BrushEven : BrushOdd;
}

The problem is, as you might guess from the title, the background for an item in the ListView is not re-rendered whenever I select it. In my experience, this triggers the fact that I did not handle event fired when the selection is made. So I added

    <ListView x:Name="myList" SelectionChanged="OnItemSelected">
           <!-- Omitted code -->
    </ListView>

Unfortunately, there is no place in the API telling me how to properly redraw the ListView. The closest thing I could get is by this stupid code:

void MainPage::OnItemSelected(Platform::Object^ sender, Windows::UI::Xaml::Controls::SelectionChangedEventArgs^ e)
{
    // This is to trigger OnItemTemplateChanged which have a side effect of redrawing the whole list view.
    myList->ItemTemplate = myList->ItemTemplate;
}

Now, the new problem is that the list view flickers after every selection and the viewing state of the list is totally lost (e.g. the list automatically scrolls back to the beginning of the list).

So I want to ask for the proper way to force a ListView (or any other UI element) to redraw itself.


回答1:


It turns out that ListView create ListViewItem using the supplied data template for each "logical" (non-UI information) item. The methods ListView::ContainerFromIndex and ListView::ContainerFromItem allows one to access the ListViewItem from a given index or from the logical item. Then we can manipulate the property ListViewItem::ContentTemplateRoot to achieve what we need.

void MainPage::OnSelectionChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::SelectionChangedEventArgs^ e)
{
    auto listview = (ListView^)sender;

    // Restore background for unselected item
    auto list = reinterpret_cast<IVector<Object^>^>(listview->ItemsSource);
    for (auto item : e->RemovedItems)
    {
        unsigned int index;
        list->IndexOf(item, &index);
        auto container = (ListViewItem^)listview->ContainerFromIndex(index);

        auto border = (Border^)container->ContentTemplateRoot;
        border->Background = index % 2 == 0 ? BrushEven : BrushOdd;

        // This null check is necessary because when the [unselected] item goes out of view, ListView seems to reuse the ListViewItem to display other item and simply return nullptr.
        if (container != nullptr)
        {
            auto border = (Border^)container->ContentTemplateRoot;
            border->Background = DefaultBrushTransparent;
        }
    }

    // Highlight the selected item
    for (auto item : e->AddedItems)
    {
        auto container = (ListViewItem^)listview->ContainerFromItem(item);
        auto border = (Border^)container->ContentTemplateRoot;
        border->Background = BrushHighlight;
    }
}

This solution is not perfect. If one selects an item and scroll long down the list so that the selected item is out of view and then select a new item, the background of the unselected is not restored to normal state, so when one nagivates upward, the item appears selected!?

The best i.e. fully working solution comes from Romasz's comment though such integration-of-UI-into-model design is less than ideal.



来源:https://stackoverflow.com/questions/28621914/force-redraw-on-listview-in-windows-store-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!