【问题标题】:ListView ignoring drag and drop when setting a ItemTemplate设置 ItemTemplate 时 ListView 忽略拖放
【发布时间】:2017-12-05 11:13:45
【问题描述】:

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

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

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

所以选项卡看起来很棒,但所有过去可以工作的功能(如拖放)都不再工作了。当我删除 ControlTemplate 时,ListView 只显示一个小字符串。

这就是正在发生的事情

我的 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" >

我确定问题不在于拖放方法。

要创建一个新项目,我只需使用 Add。当然,我检查了 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>

【问题讨论】:

  • 那是因为您不应该更改 ContentTemplate... 它具有拖放功能的所有挂钩,您将其替换为数据模板...跨度>
  • 但是@JustinXL 我需要在 ListView 项目中包含一些样式和其他信息。没有 ContentTemplate 怎么办?
  • 如果您想要不同的样式,请在列表视图项的样式中进行。
  • 我不认为可以从样式中插入按钮或右键单击菜单上下文。我明白你的意思,但这对我不起作用。将再次尝试将其更改为 DataTemplate,但每次添加新项目 id 时都没有遵循我设置的 DataTemplate。
  • 对我来说这两种声音都是可能的。但是如果你真的想要自己的控件模板,你应该考虑构建自己的拖放逻辑。

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


【解决方案1】:

原因是您正在使用ControlTemplate 并在其中嵌入ListViewItemListViewItems 由控件自动创建以包含项目,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,而是一个自定义类。如果您直接使用DataModelItemTemplate 将按预期应用:

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

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

【讨论】:

  • 我准确地跟着你,做DataTemplate,删除嵌入的ListViewItem并将ItemTemplate="{StaticResource listViewItemTemplate}"放入中。然而,我没有成功。并且应用程序的行为就像没有项目模板一样。我仔细检查了名称,一切看起来都很好。
  • 这很不寻常。我的应用程序中有这个确切的解决方案,它也实现了选项卡式 UI。您能否尝试在一个简单的解决方案中实现它并将其发布在此处以便我可以查看代码本身?
  • 这里是一个简单解决方案的 GitHub 链接,其中包含可能影响它的所有内容:GitHub Repository
  • 我已经更新了我的答案,并解释了我的发现:-)
  • 一个非常简单的解决方案!谢谢你马丁。将改进代码并使用它更新 GitHub 存储库,以便其他人可以使用它。感激不尽!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 2011-11-04
相关资源
最近更新 更多