ListView在设置ItemTemplate时忽略拖放

时间:2017-07-01 18:51:09

标签: c# xaml listview uwp windows-10-universal

我已经设置了ListView来管理我的应用上的标签。因此,用户可以将选项卡拖放到应用程序的新实例并重新排序选项卡。一切顺利,直到我在ListView上为Itens设置ControlTemplate。

我使用了ControlTemplate,因为当我直接添加ListView.ItemTemplate时,它不会工作(它不会影响listview项)。所以在添加新项目之前我使用它:

tab.Template = (ControlTemplate)this.Resources["listViewItemTemplate"];

因此标签看起来很棒,但过去工作的所有功能(如拖放)都不再适用。当我删除ControlTemplate时,ListView只显示一个小字符串。

这就是发生的事情 This is what is happening

我的ListView代码:

<ListView x:Name="TabsListView" 
     CanDragItems="True"
     AllowDrop="True"
     DragEnter="TabsListView_DragEnter"
     Drop="TabsListView_Drop"
     ScrollViewer.VerticalScrollBarVisibility="Disabled
     CanReorderItems="True"
     DragItemsStarting="TabsListView_DragItemsStarting"
     ItemClick="TabsListView_ItemClick" >

我确信问题不在拖放方法上。

要创建新项目,我只需使用添加。当然,我检查了ControlTemplate中的每一项都知道它没有阻塞任何东西。

控制模板是:

<ControlTemplate x:Key="listViewItemTemplate" >
    <ListViewItem>
        <Grid Tapped="Grid_Tapped" Width="180" Margin="-12,-12,-12,0">
            <TextBlock Text="{Binding Name}" Margin="5,6,0,0"></TextBlock>
        </Grid>
    </ListViewItem>
</ControlTemplate>

1 个答案:

答案 0 :(得分:0)

原因是您正在使用ControlTemplate并在其中嵌入ListViewItem。控件自动创建ListViewItems以包含项目,ItemTemplate是此容器的内容的模板。所以看起来应该是这样的:

<DataTemplate x:Key="listViewItemTemplate" >
    <Grid Tapped="Grid_Tapped" Width="180" Margin="-12,-12,-12,0">
        <TextBlock Text="{Binding Name}" Margin="5,6,0,0"></TextBlock>
    </Grid>
</ControlTemplate>

<ListView ... 
      ItemTemplate="{ThemeResource listViewItemTemplate}">
        ...
</ListView>

此外,如果要设置ListViewItem(容器)的样式,可以使用TargetType="ListViewItem"创建样式并将其设置为ListView.ItemContainerStyle

<Style TargetType="ListViewItem" x:Key="TabListViewItemContainerStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListViewItem">
                <Grid x:Name="ContentBorder">
                    ... some template with ContentPresenter:
                    <ContentPresenter x:Name="ContentPresenter" ... />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<ListView ...
    ItemContainerStyle="{StaticResource TabListViewItemContainerStyle}">
     ...
</ListView>

您可以在C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.15063.0\Generic

中找到默认样式

更新

我检查了代码并发现了问题。您实际在做的是直接在代码中添加ListViewItems

ListViewItem tab = new ListViewItem();
DataModel model = new DataModel();
model.Name = $"NewTab {counter}";
tab.DataContext = model;
tab.Content = model.ToString();
TabsListView.Items.Add(tab);

不幸的是,这不起作用,因为当ListView看到类型为ListViewItem的项目时,它只是将其添加到列表中,但是ItemTemplate不适用于它,因为它已应用仅当项目不是UIElement而是自定义类时。如果您直接使用DataModel,则ItemTemplate将按预期应用:

DataModel model = new DataModel();
model.Name = $"NewTab {counter}";
TabsListView.Items.Add(model);

ListView遇到DataModel,知道只有一个类不是UIElement,因此它会在内部创建ListViewItem,将ItemContainerStyle应用于它,然后使用ItemTemplate创建将在ListViewItem的ContentPresenter中显示的UI。最好使用这种方法,因为它可以让您更好地解耦,因为您不必在代码隐藏中创建基于UI的类,并且您可以获得更多控制(因为您可以更改项目的样式以及容器)。