我目前正在使用Windows Phone 8应用程序并遇到长列表选择器(LLS)的一些问题。 列表框通过使用TranslateY值来执行此操作:
UIElement scrollContent = (UIElement)this.targetScrollViewer.Content;
CompositeTransform ct = scrollContent.RenderTransform as CompositeTransform;
//ct.TranslateY: I need this value in Viewport's LLS to detect exactly the distance moving from the TOP
我尝试使用LLS检测pull-to-refresh,但它有一些缺陷(使用Mouse Enter,MOve和Leave):
double manipulationStart = 0;
double manipulationEnd = 0;
void targetLLS_MouseEnter(object sender, MouseEventArgs e)
{
if (!this.IsRefreshing)
{
var pos = e.GetPosition(null);
manipulationStart = pos.Y;
IsMoving = false;
}
}
private void targetLLS_MouseMove(object sender, MouseEventArgs e)
{
if (!this.IsRefreshing)
{
var pos = e.GetPosition(null);
manipulationEnd = pos.Y;
IsMoving = true;
double TranslateY = manipulationEnd - manipulationStart;
if (TranslateY > this.PullThreshold)
{
this.PullDistance = 100;
this.PullFraction = 1.0;
activityState = PullDownToRefreshPanel.ReadyToReleaseVisualState;
}
else if (TranslateY > 0)
{
this.PullDistance = 100;
double threshold = this.PullThreshold;
this.PullFraction = 1;// threshold == 0.0 ? 1.0 : Math.Min(1.0, TranslateY / threshold);
activityState = PullDownToRefreshPanel.PullingDownVisualState;
}
else
{
this.PullDistance = 0;
this.PullFraction = 0;
activityState = PullDownToRefreshPanel.InactiveVisualState;
}
VisualStateManager.GoToState(this, activityState, false);
}
}
bool IsMoving = false;
void targetLLS_MouseLeave(object sender, MouseEventArgs e)
{
if (!this.IsRefreshing && IsMoving)
{
double TranslateY = manipulationEnd - manipulationStart;
EventHandler handler = this.RefreshRequested;
if (this.targetLLS.IsAtTop()
&& (activityState == PullDownToRefreshPanel.ReadyToReleaseVisualState))// TranslateY >= this.PullThreshold
{
if (handler != null)
{
IsRefreshing = true;
handler(this, EventArgs.Empty);
}
}
IsMoving = false;
}
PullDistance = 0;
PullFraction = 0;
manipulationStart = 0;
manipulationEnd = 0;
activityState = PullDownToRefreshPanel.InactiveVisualState;
//VisualStateManager.GoToState(this, activityState, false);
}
我如何处理以下模板:
<Style x:Key="ViewportControlStyle" TargetType="ViewportControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ViewportControl">
<ContentPresenter x:Name="ContentElement" Cursor="{TemplateBinding Cursor}" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="LongListSelectorNormalStyle" TargetType="phone:LongListSelector">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="phone:LongListSelector">
<Grid Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ScrollStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="00:00:00.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Scrolling">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="VerticalScrollBar"/>
</Storyboard>
</VisualState>
<VisualState x:Name="NotScrolling"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Margin="{TemplateBinding Padding}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ViewportControl x:Name="ViewportControl" HorizontalContentAlignment="Stretch" VerticalAlignment="Top" Style="{StaticResource ViewportControlStyle}"/>
<ScrollBar x:Name="VerticalScrollBar" Grid.Column="0" Margin="4,0,4,0" Opacity="0" Orientation="Vertical" HorizontalAlignment="Right"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我的项目需要实现拉动功能所以请帮助我。 谢谢你的阅读!
答案 0 :(得分:1)
您可以使用ItemRealized事件并使用ListHeader(或ListFooter从底部拉出来)来完成此操作。在ItemRealized事件中,您检查该项是否是您的标题对象。如果它然后加载更多项目。
每次LongListSelector项获取要在屏幕上显示的UI容器时,都会引发ItemRealized事件。换句话说,每当项目进入当前视口上方或下方的UI缓冲区时,都会引发 ItemRealized 事件。事件参数属性 ItemKind 表示UI容器是项, ListHeader , GroupHeader 还是 ListFooter 即可。使用属性 Container.Content ,您可以获得与实现的UI容器关联的实际对象。这样,您就可以监视UI容器缓冲区中的对象。
请注意此示例中的应用代码如何包含私有变量 _offsetKnob 。这有助于微调LongListSelector滚动体验,有助于确定何时加载更多项目,具体取决于项目模板的重量,或者响应来自发送数据的服务的响应速度。
来自他们提供的Twitter sample
void resultList_ItemRealized(object sender, ItemRealizationEventArgs e)
{
if (!_viewModel.IsLoading && resultList.ItemsSource != null && resultList.ItemsSource.Count >= _offsetKnob)
{
if (e.ItemKind == LongListSelectorItemKind.Item)
{
if ((e.Container.Content as TwitterSearchResult).Equals(resultList.ItemsSource[resultList.ItemsSource.Count - _offsetKnob]))
{
_viewModel.LoadPage(_searchTerm, _pageNumber++);
}
}
}
}
答案 1 :(得分:0)
这并非完全无足轻重,但一种方法是使用GestureService
this.gestureListener = GestureService.GetGestureListener(containerPage);
this.gestureListener.DragStarted += gestureListener_DragStarted;
this.gestureListener.DragCompleted += gestureListener_DragCompleted;
this.gestureListener.DragDelta += gestureListener_DragDelta;
然而,它有一些错误。例如,DragCompleted并不总是被引发,所以你需要使用ManipulationCompleted事件仔细检查它,这似乎更可靠。
containerPage.ManipulationStarted += delegate { this.manipulationInProgress = true; };
containerPage.ManipulationCompleted += delegate
{
this.manipulationInProgress = false;
PerformDragComplete();
};
另一个问题是DragDelta偶尔会报告错误的坐标。所以你需要这样的修复:
Point refPosition = e.GetPosition(null);
if (refPosition.X == 0 && refPosition.Y == 0)
{
Tracer.WriteLine("Skipping buggy event");
return;
}
最后,您可以找到列表是否一直位于顶部:
public double VerticalOffset
{
get
{
ViewportControl viewportControl = this.FindChildByName("ViewportControl") as ViewportControl;
if (viewportControl != null)
{
Tracer.WriteLine("ViewPort.Bounds.Top=" + viewportControl.Bounds.Top + " ViewPort.Top=" + viewportControl.Viewport.Top.ToString() + " State=" + this.ManipulationState);
return viewportControl.Bounds.Top - viewportControl.Viewport.Top;
}
return double.NaN;
}
}