FrameworkElement.EffectiveViewportChanged 事件
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
在 FrameworkElement的有效视区 更改时发生。
// Register
event_token EffectiveViewportChanged(TypedEventHandler<FrameworkElement, EffectiveViewportChangedEventArgs const&> const& handler) const;
// Revoke with event_token
void EffectiveViewportChanged(event_token const* cookie) const;
// Revoke with event_revoker
FrameworkElement::EffectiveViewportChanged_revoker EffectiveViewportChanged(auto_revoke_t, TypedEventHandler<FrameworkElement, EffectiveViewportChangedEventArgs const&> const& handler) const;
public event TypedEventHandler<FrameworkElement,EffectiveViewportChangedEventArgs> EffectiveViewportChanged;
function onEffectiveViewportChanged(eventArgs) { /* Your code */ }
frameworkElement.addEventListener("effectiveviewportchanged", onEffectiveViewportChanged);
frameworkElement.removeEventListener("effectiveviewportchanged", onEffectiveViewportChanged);
- or -
frameworkElement.oneffectiveviewportchanged = onEffectiveViewportChanged;
Public Custom Event EffectiveViewportChanged As TypedEventHandler(Of FrameworkElement, EffectiveViewportChangedEventArgs)
事件类型
注解
滚动控件允许用户平移/滚动占用比 UI 中可用空间更多的内容。 用户看到的内容部分称为 视区。
EffectiveViewportChanged 事件提供多条信息:
EffectiveViewport
EffectiveViewport 是子树中包含 FrameworkElement 的所有已知视口的交集。 例如,如果有两个或更多个视区 (嵌套在另一个 ScrollViewer) 不重叠的 ScrollViewer ,则 EffectiveViewport 为空 Rect。
注意
若要让框架 知道 滚动控件的视区,该控件必须事先使用 UIElement.RegisterAsScrollPort 方法注册它。 框架在确定有效视区时使用已注册元素的 剪辑 。
滚动控件的视区更改时,它必须调用其 InvalidateViewport 方法,以通知框架其视区已更改,并且侦听有效视区的任何子元素都需要收到更改通知。
EffectiveViewport 在 FrameworkElement 的坐标空间中提供。 无需使用视区 Rect 执行 TransformToVisual。
在包含单个元素的 ScrollViewer 的简单方案中,EffectiveViewportChanged 事件提供类似于 ViewChanged 事件的视区更新。 main区别在于,在布局的排列传递之后引发 EffectiveViewportChanged 事件。
例如,此 ...
<ScrollViewer>
<Grid Height="4000" Width="4000"
EffectiveViewportChanged="Grid_EffectiveViewportChanged"/>
</ScrollViewer>
...提供与此类似的视区信息...
<ScrollViewer ViewChanged="ScrollViewer_ViewChanged">
<Grid Height="4000" Width="4000"/>
</ScrollViewer>
MaxViewport
MaxViewport 类似于 EffectiveViewport,但它不是表示已知视口的简单交集,而是表示视口的交集,就好像每个视区都已进入任何外部视口的视图一样。 生成的 Rect 表示两项内容:
- 根据当前视区大小) ,EffectiveViewport 可以 (的最大大小,以及
- 相对于 FrameworkElement 的最大有效视区的位置。
此信息可用于衡量 FrameworkElement 应预先生成的内容,以在滚动到视图中 之前 可能填充视区的位置和内容量。
注意
通过直接输入(如触摸或笔)滚动由系统在单独的进程中进行处理。 默认情况下,滚动以异步方式处理到 UI 线程。 由于元素创建的固有成本,执行虚拟化的控件可能需要在进入视区之前预先生成内容。
延迟所有内容准备,直到进入视图可能会导致用户滚动体验不佳。 用户可能会看到空白或断断续续,这两种症状都是 UI 线程无法跟上平移速度的症状。
MaxViewport 的位置在 FrameworkElement 的坐标空间中报告。 如果将 MaxViewport 转换为 FrameworkElement 的上级链中第一个视区的坐标空间, 则 Rect 将位于第一个视区的边界内。
BringIntoViewDistanceX 和 Y
这些值指示 FrameworkElement 在其所有视区中如何最接近地可见。
如果值大于零,但小于 ActualWidth / ActualHeight ,则元素部分位于用户可见视区内。 如果值为零,则 FrameworkElement 完全位于用户可见视区中。
提示
这不能保证该元素对用户可见,因为 Z 顺序较高的其他元素可能仍会遮挡 FrameworkElement。
更正式地说,这些值是在满足对 StartBringIntoView 的调用时,FrameworkElement 将转换的绝对距离之和。 这些值不考虑滚动控件禁用滚动的可能性。
<ListView x:Name="lv">
<ListView.ItemTemplate>
<DataTemplate x:DataType="x:String">
<UserControl Tag="{x:Bind}"
EffectiveViewportChanged="Item_EffectiveViewportChanged"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
private void Item_EffectiveViewportChanged(FrameworkElement sender, EffectiveViewportChangedEventArgs args)
{
// If we wanted to know if a list item (w/ vertical scrolling only) is partially within the viewport
// then we can just check the BringIntoViewDistanceY of the event args. If the distance is 0 then the item is fully within
// the effective viewport. If the BringIntoViewDistanceY is less than the sender's ActualHeight, then its
// partially within the effective viewport.
// The EffectiveViewport rect is relative to the sender, so we can use it to know where the element is within the viewport.
// NOTE: "Within the viewport" != visible to the user's eye, since another element may overlap and obscure it.
if (args.BringIntoViewDistanceY < sender.ActualHeight)
{
Debug.WriteLine($"Item: {sender.Tag} has {sender.ActualHeight - args.BringIntoViewDistanceY} pixels within the viewport");
}
else
{
Debug.WriteLine($"Item: {sender.Tag} has {args.BringIntoViewDistanceY - sender.ActualHeight} pixels to go before it is even partially visible");
}
// Consider disconnecting from the effective viewport when not needed. Otherwise, it is called on every viewport change.
//lv.EffectiveViewportChanged -= Item_EffectiveViewportChanged;
}
行为
- 如果父级和子级的有效视区都发生更改,父级将在子级之前收到通知。
- 仅针对 UI 树中参与布局的元素引发 事件。 例如,如果元素不在活动树中,或者元素或其任何上级元素的 Visibility 属性设置为 Collapsed,则不会引发此事件。
- 尽管有效视区确实考虑了所有上级元素的呈现转换,但它不考虑剪切 (除滚动控件注册的元素剪辑以外的效果作为其视区) 。
- 由于其他元素的 Z 顺序较高,有效视区不考虑遮挡。