TiltEffect and LongListSelector

2020-07-02 11:19发布

问题:

I am trying to use the TiltEffect from the Silverlight toolkit within a LongListSelector. This is how the element is declared in XAML:

<controls:PivotItem Header="Pivot Item">

  <controls:PivotItem.Resources>

    <DataTemplate x:Key="LongListSelectorGroupHeaderTemplate">
      <Border Background="{StaticResource PhoneAccentBrush}"
              Margin="10,20,0,0"
              HorizontalAlignment="Left"
              VerticalAlignment="Center"
              Height="{StaticResource PhoneFontSizeExtraExtraLarge}"
              Width="{StaticResource PhoneFontSizeExtraExtraLarge}">
        <TextBlock Text="{Binding Name}"
                   Style="{StaticResource PhoneTextExtraLargeStyle}"
                   Foreground="White"
                   VerticalAlignment="Bottom"
                   HorizontalAlignment="Left" />
      </Border>
    </DataTemplate>

    <DataTemplate x:Key="LongListSelectorGroupItemTemplate">
      <Border Background="{StaticResource PhoneAccentBrush}"
              Margin="10"
              Height="{StaticResource PhoneFontSizeExtraExtraLarge}"
              Width="{StaticResource PhoneFontSizeExtraExtraLarge}">
        <TextBlock Text="{Binding Name}"
                   Style="{StaticResource PhoneTextExtraLargeStyle}"
                   Foreground="White"
                   VerticalAlignment="Bottom"
                   HorizontalAlignment="Left" />
      </Border>
    </DataTemplate>

    <DataTemplate x:Key="LongListSelectorItemTemplate">
      <StackPanel Grid.Column="1"
                  VerticalAlignment="Top"
                  Orientation="Horizontal"
                  toolkit:TiltEffect.IsTiltEnabled="True">

        <toolkit:GestureService.GestureListener>
          <toolkit:GestureListener Tap="OnLongListSelectorTapped" />
        </toolkit:GestureService.GestureListener>

        <Image  Source="{Binding ImageSource}"
                MinHeight="32"
                MinWidth="32"
                MaxHeight="48"
                MaxWidth="48" />

        <TextBlock Text="{Binding Name}"
                   Style="{StaticResource PhoneTextExtraLargeStyle}"
                   Margin="12,10,12,0" />

      </StackPanel>
    </DataTemplate>

  </controls:PivotItem.Resources>

  <toolkit:LongListSelector ItemTemplate="{StaticResource LongListSelectorItemTemplate}"
                            GroupHeaderTemplate="{StaticResource LongListSelectorGroupHeaderTemplate}"
                            GroupItemTemplate="{StaticResource LongListSelectorGroupItemTemplate}">

    <toolkit:LongListSelector.GroupItemsPanel>
      <ItemsPanelTemplate>
        <toolkit:WrapPanel />
      </ItemsPanelTemplate>
    </toolkit:LongListSelector.GroupItemsPanel>

  </toolkit:LongListSelector>

</controls:PivotItem>

Unfortunately, this isn't working. The tap gesture fires when tapping on an item, but the animation does not play. I've tried setting TiltEffect.IsTiltEnabled property on the LongListSelector, the PivotItem and the parent page but none of them work.

I have another PivotItem that contains a simple ListBox with an ItemTemplate that is very similar to LongListSelectorItemTemplate above. Setting the TiltEffect.IsTiltEnabled property to true within its DataTemplate works as desired.

What am I doing wrong in the case of the LongListSelector?

回答1:

If you wrap your ItemTemplate in a ListBoxItem, it will tilt accordingly:

<DataTemplate x:Key="LongListSelectorItemTemplate">
  <ListBoxItem>
    <StackPanel Grid.Column="1"
                VerticalAlignment="Top"
                Orientation="Horizontal"
                toolkit:TiltEffect.IsTiltEnabled="True">

      <toolkit:GestureService.GestureListener>
        <toolkit:GestureListener Tap="OnLongListSelectorTapped" />
      </toolkit:GestureService.GestureListener>

      <Image  Source="{Binding ImageSource}"
              MinHeight="32"
              MinWidth="32"
              MaxHeight="48"
              MaxWidth="48" />

      <TextBlock Text="{Binding Name}"
                 Style="{StaticResource PhoneTextExtraLargeStyle}"
                 Margin="12,10,12,0" />
    </StackPanel>
  </ListBoxItem>
</DataTemplate>


回答2:

The way TiltEffect works is that is contains a list of Types that it will tilt, by deafult these are Button and ListBoxItem. It then drills down through the visual tree from where you turn it on and adds the effect to all instances of those classes. So your LongListSelector.ItemTemplate needs to contain a tiltable item. The easiest way to do this is with an invisible button, that way you do not need to edit your TiltEffect and can use it straight out of the toolkit. If you really don't want the button, then you need some other ContentControl to wrap your template from which you can trigger the tilting. Then add that class to the TiltEffect list.

TiltEffect.TiltableItems.Add(typeof(MyTiltingContentControl))

I use this style on my button to make it invisible.

<Style x:Key="TiltButtonStyle" TargetType="Button">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="BorderBrush" Value="{x:Null}" />
        <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
        <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
        <Setter Property="Padding" Value="0,0,0,0"/>
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid Background="Transparent">
                        <Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="0" Margin="0,8,0,0">
                            <ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>


回答3:

Step-by-step instructions on how to use the tilt effect can be found on MSDN



回答4:

Adding this portion of code between the "Style" Tag in a Button template did exactly what I wanted. Make the button keep it's color when "tilted". I have set the button background to PhoneAccentBrush, so the user decides on the app look and feel with his theme settings.

<Style x:Key="MetroButton" TargetType="Button">
    <Setter Property="Background" Value="{StaticResource PhoneAccentBrush}"/>
    <Setter Property="Height" Value="200"/>
    <Setter Property="Width" Value="200"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid Background="Transparent">
                    <Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="0" Margin="0,8,0,0">
                        <ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>


回答5:

TiltEffect.IsTiltEnabled="True" goes on the PhoneApplicationPage element, change your ItemTemplate to contain a button and it will work.



回答6:

Create a new control inherits stackpanel

public class TiltStackPanel : StackPanel
    {
        public TiltStackPanel() {}
    }

then add this control TiltEffect.cs

static TiltEffect()
    {
      // For extra fun, add this to the list: typeof(Microsoft.Phone.Controls.PhoneApplicationPage)
      TiltableItems = new List<Type>() { typeof(ButtonBase), typeof(ListBoxItem), typeof(TiltStackPanel)};
      UseLogarithmicEase = false;
    }

Use this TiltStackPanel inside your template of longlistselector