在windows应用商店应用程序中强制重画ListView
我正在使用@Romasz的回答为在windows应用商店应用程序中强制重画ListView,listview,windows-store-apps,c++-cx,Listview,Windows Store Apps,C++ Cx,我正在使用@Romasz的回答为ListView项目提供备用背景。我更改它以突出显示所选项目,如下所示: <local:AlternateConverter CurrentList="{Binding ElementName=myList, Path=ItemsSource}" HighlightIndex="{Binding ElementName=myList, Path=SelectedIndex}"
ListView
项目提供备用背景。我更改它以突出显示所选项目,如下所示:
<local:AlternateConverter CurrentList="{Binding ElementName=myList, Path=ItemsSource}"
HighlightIndex="{Binding ElementName=myList, Path=SelectedIndex}"
x:Key="AlternateConverter"/>
问题是,正如您可能从标题中猜到的那样,ListView
中某个项目的背景不会在我选择它时重新呈现。根据我的经验,这会触发一个事实,即我没有处理在进行选择时触发的事件。所以我补充说
<ListView x:Name="myList" SelectionChanged="OnItemSelected">
<!-- Omitted code -->
</ListView>
现在,新的问题是列表视图在每次选择后都会闪烁,并且列表的查看状态完全丢失(例如,列表会自动回滚到列表的开头)
因此,我想寻求一种正确的方法来强制
列表视图
(或任何其他UI元素)重新绘制自身。结果是列表视图
使用为每个“逻辑”(非UI信息)项提供的数据模板创建列表视图项
。方法ListView::ContainerFromIndex
和ListView::ContainerFromItem
允许从给定索引或逻辑项访问ListViewItem
。然后,我们可以操纵属性ListViewItem::ContentTemplateRoot
,以实现我们需要的功能
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;
}
}
void主页::OnSelectionChanged(平台::对象^sender,Windows::UI::Xaml::控件::SelectionChangedEventArgs ^e)
{
自动列表视图=(列表视图^)发送方;
//还原未选定项目的背景
自动列表=重新解释转换(listview->ItemsSource);
用于(自动项目:e->RemovedItems)
{
无符号整数索引;
列表->索引(项目和索引);
自动容器=(ListViewItem^)listview->ContainerFromIndex(索引);
自动边框=(边框^)容器->ContentTemplateRoot;
边框->背景=索引%2==0?刷偶数:刷奇数;
//此空检查是必要的,因为当[unselected]项退出视图时,ListView似乎重用ListViewItem来显示其他项,并简单地返回nullptr。
if(容器!=nullptr)
{
自动边框=(边框^)容器->ContentTemplateRoot;
边框->背景=DefaultBrushTransparent;
}
}
//突出显示所选项目
用于(自动项目:e->AddedItems)
{
自动容器=(ListViewItem^)listview->ContainerFromItem(项目);
自动边框=(边框^)容器->ContentTemplateRoot;
边框->背景=BrushHighlight;
}
}
这个解决方案并不完美。如果选择一个项目并向下滚动列表,使所选项目不在视图中,然后选择一个新项目,则未选中项目的背景不会恢复到正常状态,因此当一个项目向上移动时,该项目显示为选中
最好的,即完全工作的解决方案来自Romasz的评论,尽管将UI集成到模型设计中并不理想。我有两个快速的想法:1。在您的项目中定义一个属性,该属性将负责背景颜色,它甚至可以与SPROPRATE CONVERTOR一起使用,2。选择更改后,不要更改itemtemplate,只更改取消选择的项目的颜色-我认为这也可以在xaml中完成。
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;
}
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;
}
}