pcn*_*ird 5 c# xaml windows-phone windows-phone-8.1
我有UserControl一个Grid被订阅的Holding事件.问题是该Holding事件触发了我所定位的项目以及该项目中的其他一些项目ListView.顺便说一下,我正在使用控件作为DataTemplate.
<ListView ItemsSource="{Binding ...}" Margin="0, 0, 0, 0">
...
<ListView.ItemTemplate>
<DataTemplate>
<local:MyUserControl/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Run Code Online (Sandbox Code Playgroud)
用户控制代码隐藏:
private bool isDescriptionVisible = false;
private void Grid_Holding(object sender, HoldingRoutedEventArgs e)
{
if (!isDescriptionVisible)
{
DescriptionFadeIn.Begin();
isDescriptionVisible = true;
}
}
private void Grid_Tapped(object sender, TappedRoutedEventArgs e)
{
if (isDescriptionVisible)
{
DescriptionFadeOut.Begin();
isDescriptionVisible = false;
}
}
Run Code Online (Sandbox Code Playgroud)
用户控制内容:
<Grid.Resources>
<Storyboard x:Name="FadeIn">
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DescriptionLayer"
Duration="0:0:0.3" To=".8"/>
</Storyboard>
<Storyboard x:Name="FadeOut">
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DescriptionLayer"
Duration="0:0:0.3" To="0"/>
</Storyboard>
</Grid.Resources>
<Grid Margin="0, 0, 0, 48" Holding="Grid_Holding" Tapped="Grid_Tapped">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Image Source="{Binding Img}" Stretch="UniformToFill" Height="240" Width="450"/>
<Grid x:Name="DescriptionLayer" Background="Black" Opacity="0">
<TextBlock Text="{Binding Description}" FontSize="16" TextWrapping="Wrap" Margin="0, 9, 0, 0" MaxHeight="170" TextTrimming="CharacterEllipsis"/>
</Grid>
<StackPanel Grid.Row="1" Margin="12">
<TextBlock Text="{Binding Author}" FontSize="16"/>
<TextBlock Text="{Binding Title}" FontSize="18"/>
</StackPanel>
</Grid>
Run Code Online (Sandbox Code Playgroud)
我无法在DataTemplate中包含的项目上使用故事板,因此强制我使用将其内容移动到UserControl.
这个问题与虚拟化有关吗?我怎样才能解决这个问题?
替代方案会做.
更新:
一些SO帖子表明回收模式导致物品被重复使用.我已添加
VirtualizingStackPanel.VirtualizationMode="Standard"到我的ListView,但问题出乎意料地持续存在.
所以现在我需要找出一种方法来防止其他项重复相同的不透明度值(这不是数据绑定,因为它是通过故事板设置的).
更新2:
现在,当显示项目退出视图时,保持显示项目完全消失的描述:
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
Run Code Online (Sandbox Code Playgroud)
我喜欢你在这里尝试做的事情。对于触摸屏设备,我们没有MouseOver事件,因此当您想要显示一些额外信息而不弄乱 UI 时,这是方法之一。
然而,一个更简洁的解决方案是创建一个可重用的Behavior封装所有 UI 逻辑和动画的解决方案。
为此,您首先需要包含引用Behaviors SDK (XAML)。
实施过程Behavior非常简单。这AssociatedObject将是Grid接收触摸事件的实例,然后您需要创建一个DependencyProperty TextBlockName来检索描述TextBlock实例。获得实例后,您只需用 C# 为其编写动画即可。
public class ShowHideDescriptionBehavior : DependencyObject, IBehavior
{
public string TextBlockName
{
get { return (string)GetValue(TextBlockNameProperty); }
set { SetValue(TextBlockNameProperty, value); }
}
// Using a DependencyProperty as the backing store for TextBlockName. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TextBlockNameProperty =
DependencyProperty.Register("TextBlockName", typeof(string), typeof(ShowHideDescriptionBehavior), new PropertyMetadata(string.Empty));
public DependencyObject AssociatedObject { get; set; }
public void Attach(DependencyObject associatedObject)
{
this.AssociatedObject = associatedObject;
var panel = (Panel)this.AssociatedObject;
panel.Holding += AssociatedObject_Holding;
panel.Tapped += AssociatedObject_Tapped;
}
private void AssociatedObject_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
var animation = new DoubleAnimation
{
Duration = TimeSpan.FromMilliseconds(300),
To = 0
};
Storyboard.SetTarget(animation, this.DescriptionTextBlock);
Storyboard.SetTargetProperty(animation, "Opacity");
var storyboard = new Storyboard();
storyboard.Children.Add(animation);
storyboard.Begin();
}
private void AssociatedObject_Holding(object sender, Windows.UI.Xaml.Input.HoldingRoutedEventArgs e)
{
var animation = new DoubleAnimation
{
Duration = TimeSpan.FromMilliseconds(300),
To = 0.8
};
Storyboard.SetTarget(animation, this.DescriptionTextBlock);
Storyboard.SetTargetProperty(animation, "Opacity");
var storyboard = new Storyboard();
storyboard.Children.Add(animation);
storyboard.Begin();
}
private TextBlock _descriptionTextBlock;
private TextBlock DescriptionTextBlock
{
get
{
if (_descriptionTextBlock == null)
{
var panel = (Panel)this.AssociatedObject;
// todo: add validation
_descriptionTextBlock = (TextBlock)panel.FindName(this.TextBlockName);
}
return _descriptionTextBlock;
}
}
public void Detach()
{
var panel = (Panel)this.AssociatedObject;
panel.Holding -= AssociatedObject_Holding;
panel.Tapped -= AssociatedObject_Tapped;
}
}
Run Code Online (Sandbox Code Playgroud)
然后可以将其Behavior附加到您的DataTemplate顶层Grid。请注意,您不再需要 aUserControl来包装它。
另外,请确保您有背景颜色,以便Grid它可以接收触摸事件。我做的最后一件事是将ListView'ItemContainerStyle更改HorizontalContentAlignment为Stretch,这样 'Grid就一直延伸到右侧。
<Page.Resources>
<DataTemplate x:Key="GroupTemplate">
<Grid Background="Transparent" Margin="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Interactivity:Interaction.Behaviors>
<local:ShowHideDescriptionBehavior TextBlockName="Description" />
</Interactivity:Interaction.Behaviors>
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110">
<Image Source="{Binding Img}" Height="110" Width="110"/>
</Border>
<StackPanel Grid.Column="1" Margin="10,0,0,0">
<TextBlock Text="{Binding Author}" Style="{StaticResource TitleTextBlockStyle}"/>
<TextBlock x:Name="Description" Opacity="0" Text="{Binding Description}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
</StackPanel>
</Grid>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" DataContext="{Binding Source={StaticResource SampleDataSource}}">
<ListView ItemTemplate="{StaticResource GroupTemplate}" ItemsSource="{Binding Groups}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
Run Code Online (Sandbox Code Playgroud)