UWP ListView - 不再调用DragOver

时间:2018-05-29 10:04:56

标签: xaml uwp uwp-xaml listviewitem

我面临一个无法解决的问题。我有一个ListView,当用户在列表视图项上拖动一个对象时,我需要自定义项目样式。由于我的州的复杂性,我不想保留扩展的ListViewItem样式的ListViewItemPresenter。因此,当我删除该演示者并定义我自己的样式(基本上是经典的内容演示者+ overlay + underlay + VisualStateGroups来定义动画)时,我不再在列表项对象上接收DragOver和Drop事件。我不明白为什么?如果我保持默认的项目容器样式它工作正常...我错过了什么?

让我进一步了解一些代码。以下是我的列表视图,用于定义 ItemTemplate ItemContainerStyle

<ListView x:Name="notebookListView"  
          ItemsSource="{x:Bind NoteBookItems}" 
          ItemTemplate="{StaticResource NotebookItemListViewTemplate}"
          ItemContainerStyle="{StaticResource notebookItemContainerStyle}"
          IsItemClickEnabled="True"
          SelectionMode="Single"
          AllowDrop="True" CanReorderItems="False" CanDragItems="True"
          DragItemsStarting="NotebookListView_DragItemsStarting"
          DragItemsCompleted="NotebookListView_DragItemsCompleted"
          ItemClick="NotebookItem_Click" />

以下是定义 DragOver Drop 方法的项目模板:

<DataTemplate x:Name="NotebookItemListViewTemplate" x:DataType="model:NotebookItem">
  <Grid x:Name="notebook" HorizontalAlignment="Left" Height="48" Width="320"
        AllowDrop="True"
        DragOver="DragOverNotebookItem" 
        Drop="DropInNotebookItem">
   [...]
  </Grid>
</DataTemplate>

最终我的扩展项容器样式:

<Style x:Key="notebookItemContainerStyle" TargetType="ListViewItem">
  <!-- all default setter properties ... -->
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ListViewItem">
        <!-- Here is my customization with VisualState to catch PointerOver and other events above my list items -->
        <Grid>
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal" />
              <VisualState x:Name="PointerOver">
                <Storyboard>
                  <ColorAnimation Storyboard.TargetName="overlay" Duration="0" To="{StaticResource ColorUIBlackAlpha04}" Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)" />
                </Storyboard>
              </VisualState>
              <VisualState x:Name="Pressed">
                <Storyboard>
                  <ColorAnimation Storyboard.TargetName="overlay" Duration="0" To="{StaticResource ColorUIBlackAlpha12}" Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)" />
                </Storyboard>
              </VisualState>
              <VisualState x:Name="PressedSelected">
                <Storyboard>
                  <ColorAnimation Storyboard.TargetName="overlay" Duration="0" To="{StaticResource ColorUIBlackAlpha12}" Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)" />
                </Storyboard>
              </VisualState>
              <VisualState x:Name="Selected">
                <Storyboard>
                  <ColorAnimation Storyboard.TargetName="overlay" Duration="0" To="Transparent" Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)" />
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <!-- and a Grid that contains the definition of the item content -->
          <Grid>
            <Rectangle x:Name="underlay" Stroke="Transparent" Fill="Transparent" Margin="0" />
            <ContentPresenter Margin="{TemplateBinding Padding}"
                              Background="Transparent"
                              HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                              VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
            <Rectangle x:Name="overlay" Stroke="Transparent" Fill="Transparent" Margin="0" />
          </Grid>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

使用该代码,我的项目的 DragOver 事件永远不会被触发。但是如果我使用默认的项目容器样式和默认的ListViewItemPresenter它可以正常工作。我不明白为什么......有人能帮我理解会发生什么吗?

这是默认的列表视图项容器样式,使用ListViewItemPresenter而不是我的客户:

<Style x:Key="notebookItemContainerStyle" TargetType="ListViewItem">
  <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
  <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
  <Setter Property="Background" Value="{ThemeResource ListViewItemBackground}"/>
  <Setter Property="Foreground" Value="{ThemeResource ListViewItemForeground}"/>
  <Setter Property="TabNavigation" Value="Local"/>
  <Setter Property="IsHoldingEnabled" Value="True"/>
  <Setter Property="Padding" Value="12,0,12,0"/>
  <Setter Property="HorizontalContentAlignment" Value="Left"/>
  <Setter Property="VerticalContentAlignment" Value="Center"/>
  <Setter Property="MinWidth" Value="{ThemeResource ListViewItemMinWidth}"/>
  <Setter Property="MinHeight" Value="{ThemeResource ListViewItemMinHeight}"/>
  <Setter Property="AllowDrop" Value="True"/>
  <Setter Property="UseSystemFocusVisuals" Value="True"/>
  <Setter Property="FocusVisualMargin" Value="0"/>
  <Setter Property="FocusVisualPrimaryBrush" Value="{ThemeResource ListViewItemFocusVisualPrimaryBrush}"/>
  <Setter Property="FocusVisualPrimaryThickness" Value="2"/>
  <Setter Property="FocusVisualSecondaryBrush" Value="{ThemeResource ListViewItemFocusVisualSecondaryBrush}"/>
  <Setter Property="FocusVisualSecondaryThickness" Value="1"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ListViewItem">
        <ListViewItemPresenter CheckBrush="{ThemeResource ListViewItemCheckBrush}" 
                               ContentMargin="{TemplateBinding Padding}" 
                               CheckMode="{ThemeResource ListViewItemCheckMode}" 
                               ContentTransitions="{TemplateBinding ContentTransitions}" 
                               CheckBoxBrush="{ThemeResource ListViewItemCheckBoxBrush}" 
                               DragForeground="{ThemeResource ListViewItemDragForeground}" 
                               DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}" 
                               DragBackground="{ThemeResource ListViewItemDragBackground}" 
                               DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}" 
                               FocusBorderBrush="{ThemeResource ListViewItemFocusBorderBrush}" 
                               FocusSecondaryBorderBrush="{ThemeResource ListViewItemFocusSecondaryBorderBrush}" 
                               HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 
                               Control.IsTemplateFocusTarget="True" 
                               PointerOverForeground="{ThemeResource ListViewItemForegroundPointerOver}" 
                               PressedBackground="{StaticResource UIBlackAlpha12}" 
                               PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackground}" 
                               PointerOverBackground="{StaticResource UIBlackAlpha04}" 
                               ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}" 
                               SelectedPressedBackground="Transparent" 
                               SelectionCheckMarkVisualEnabled="{ThemeResource ListViewItemSelectionCheckMarkVisualEnabled}" 
                               SelectedForeground="{ThemeResource ListViewItemForegroundSelected}" 
                               SelectedPointerOverBackground="Transparent" 
                               SelectedBackground="Transparent" 
                               VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

1 个答案:

答案 0 :(得分:0)

我可以重现您的问题,但我不知道导致此问题的原因。我会继续研究这个问题。目前,有一种解决方法。我发现你想要修改underlay overlay矩形的颜色。您可以在后面的代码中实现这一点,而不是使用Visualtreehelper在xaml中实现。

private void MYListview_SelectionChanged(object sender, SelectionChangedEventArgs e)
{

    StackPanel test = MyFindListViewChildByName(MYListview.ContainerFromItem(MYListview.SelectedItem), "MyTest") as StackPanel;
    test.Background = new SolidColorBrush(Colors.White);
}

public static DependencyObject MyFindListViewChildByName(DependencyObject parant, string ControlName)
{
    int count = VisualTreeHelper.GetChildrenCount(parant);

    for (int i = 0; i < count; i++)
    {
        var MyChild = VisualTreeHelper.GetChild(parant, i);
        if (MyChild is FrameworkElement && ((FrameworkElement)MyChild).Name == ControlName)
            return MyChild;

        var FindResult = MyFindListViewChildByName(MyChild, ControlName);
        if (FindResult != null)
            return FindResult;
    }

    return null;
}

您可以使用VisualTreeHelper获取underlay overlay Rectangle实例,然后为它们创建动画。您可以在ListViewItem事件处理程序中手动调用那些与xaml VisualStateGroup匹配的动画。