FrameworkElement.EffectiveViewportChanged 事件

定義

發生于 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) 

事件類型

Windows 需求

裝置系列
Windows 10, version 1809 (已於 10.0.17763.0 引進)
API contract
Windows.Foundation.UniversalApiContract (已於 v7.0 引進)

備註

捲動控制項可讓使用者移動流覽/捲動佔用比 UI 中可用空間更多的內容。 使用者看到的內容部分稱為 檢視區

EffectiveViewportChanged 事件提供多個資訊片段:

  1. 實際 EffectiveViewport
  2. MaxViewport的計算
  3. BringIntoViewDistanceXBringIntoViewDistanceY的純量值

EffectiveViewport

EffectiveViewport是所有已知檢視區的交集,其中包含其子樹狀結構中的FrameworkElement。 例如,如果有兩個以上的檢視區 (,另一個ScrollViewer內巢狀的ScrollViewer) 不會重迭,則 EffectiveViewport 是空的Rect

注意

若要讓架構 知道 捲動控制項的檢視區,控制項先前必須使用 UIElement.RegisterAsScrollPort 方法註冊它。 架構會在判斷有效的檢視區時,使用已註冊專案的 Clip

當捲動控制項的檢視區變更時,它必須叫用 其 InvalidateViewport 方法,以通知架構其檢視區已變更,以及接聽有效檢視區的任何子項目都必須收到變更的通知。

EffectiveViewport會在FrameworkElement的座標空間中提供。 不需要使用檢視區Rect執行TransformToVisual

在包含單一元素的 ScrollViewer 簡單案例中,EffectiveViewportChanged 事件會提供類似 ViewChanged 事件的檢視區更新。 主要差異在於 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 代表兩件事:

  1. 如果目前的檢視區大小) ,則 EffectiveViewport 可以 (的大小上限,以及
  2. 相對於 FrameworkElement的最大有效檢視區位置。

這項資訊可用來測量 FrameworkElement 在捲動到檢視 區之前 ,應該預先產生多少內容來填入檢視區。

注意

透過直接輸入捲動,例如觸控或手寫筆,是由系統在不同的進程中處理。 根據預設,捲動會以非同步方式處理至 UI 執行緒。 由於元素建立的固有成本,執行虛擬化的控制項可能需要預先產生內容,才能進入檢視區。

延遲所有內容準備,直到進入檢視為止,可能會導致使用者的捲動體驗不佳。 使用者可能會看到空白或雜亂,UI 執行緒的兩個徵兆都無法跟上移動流覽的速度。

MaxViewport的位置會在FrameworkElement的座標空間中報告。 如果 MaxViewport 已轉換成 FrameworkElement上階鏈結中第一個檢視區的座標空間, Rect 會位於該第一個檢視區的界限內。

BringIntoViewDistanceX 和 Y

這些值表示 FrameworkElement 在其所有檢視區中,要以最大方式顯示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 順序。

適用於

另請參閱