當前位置:
首頁 > 知識 > WPF:實現 ScrollViewer 滾動到指定控制項處

WPF:實現 ScrollViewer 滾動到指定控制項處

在前端 UI 開發中,有時,我們會遇到這樣的需求:在一個 ScrollViewer 中有很多內容,而我們需要實現在執行某個操作後能夠定位到其中指定的控制項處;這很像在 HTML 頁面中點擊一個鏈接後定位到當前網頁上的某個 anchor。

要實現它,首先我們需要看 ScrollViewer 為我們提供的 API,其中並沒有類似於 ScrollToControl 這樣的方法;在它的幾個以 ScrollTo 開頭的方法中,最合適的就是 ScrollToVerticalOffset 這個方法了,這個方法接受一個參數,即縱向的偏移位置。那麼,很重要的問題:我們怎麼能得到要定位的那個控制項在 ScrollViewer 中的位置呢?

在我之前寫的這篇文章中:XAML: 獲取元素的位置,有如何獲到元素相對位置的介紹,建議大家先了解一下,其中使用了 Visual.TransformToVisual 方法等。當你理解了這篇文章後,再回過頭來看本文後面的內容,就很容易了。

接下來,我們使用以下代碼,即可實現上述需求:

另外,由於通常情況下,我們會採用 MVVM 模式,因此我們可以將上述代碼封裝成一個 Action,而避免在 Code-Behind 代碼文件中添加上述代碼。

新創建的名為 ScrollToControlAction 的 Action,在其中定義兩個依賴屬性 ScrollViewer 和 TargetControl,分別表示指定的要操作的 ScrollViewer 和要定位到的控制項,然後將上述代碼放到其 Invoke 方法中即可。由於 Action 並非本文主題,所以這裡並不會展開太多的講解,可以參考以下代碼或本文後提供的 Demo 作進一步了解。

namespace ScrollTest
{
///

/// 在 ScrollViewer 中定位到指定的控制項
/// 說明:目前支持的是垂直滾動
///

public class ScrollToControlAction : TriggerAction
{
public static readonly DependencyProperty ScrollViewerProperty =
DependencyProperty.Register("ScrollViewer", typeof(ScrollViewer), typeof(ScrollToControlAction), new PropertyMetadata(null));

public static readonly DependencyProperty TargetControlProperty =
DependencyProperty.Register("TargetControl", typeof(FrameworkElement), typeof(ScrollToControlAction), new PropertyMetadata(null));

///

/// 目標 ScrollViewer
///

public ScrollViewer ScrollViewer
{
get { return (ScrollViewer)GetValue(ScrollViewerProperty); }
set { SetValue(ScrollViewerProperty, value); }
}

///

/// 要定位的到的控制項
///

public FrameworkElement TargetControl
{
get { return (FrameworkElement)GetValue(TargetControlProperty); }
set { SetValue(TargetControlProperty, value); }
}

protected override void Invoke(object parameter)
{
if (TargetControl == null || ScrollViewer == null)
{
throw new ArgumentNullException($"{ScrollViewer} or {TargetControl} cannot be null");
}

// 檢查指定的控制項是否在指定的 ScrollViewer 中
// TODO: 這裡只是指定離它最近的 ScrollViewer,並沒有繼續向上找
var container = TargetControl.FindParent;
if (container == null || container != ScrollViewer)
{
throw new Exception("The TargetControl is not in the target ScrollViewer");
}

// 獲取要定位之前 ScrollViewer 目前的滾動位置
var currentScrollPosition = ScrollViewer.VerticalOffset;
var point = new Point(0, currentScrollPosition);

// 計算出目標位置並滾動
var targetPosition = TargetControl.TransformToVisual(ScrollViewer).Transform(point);
ScrollViewer.ScrollToVerticalOffset(targetPosition.Y);
}
}
}

ScrollToControlAction.cs

其使用方法如下:

至此,結合 Action,我們以非常靈活的方式實現了本文所提出的需求。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 科技優家 的精彩文章:

ThinkPHP自動生成的控制器類
使用Github+Hexo框架搭建部署自己的博客
ReactiveCocoa源碼解析(二)Bag容器的代碼實現
Java集合-HashSet

TAG:科技優家 |

您可能感興趣

P2P周報:北京成立專項處置小組摸查「714高炮」 上海叫停高風險P2P保證險
埃及或將推出第一部「網路安全法」,明確29項處罰
每一個士兵,都不願意麵對的一項處罰,這對與他們來說,這是恥辱!
二戰時,蘇聯對60萬日軍俘虜,做出一項處理決定,女俘紛紛選擇自我了斷
士兵最怕的一項處罰是什麼?新兵:5公里,老兵:寧願15公里
菌菇易爛不好種植?這些注意事項處理好,高產也不難!
每個新兵,入伍後都會面臨的一項處罰,誰也逃脫不了!
重磅!北京互金協會緊急成立專項處置小組摸查「714」高炮亂象
「404」教授梁瑩獲7項處分?南大:以官方發布為準
對於新兵和老兵來說,都難以接受的幾項處罰,想想就發憷!
戰後德國武器堆積如山,盟軍提出兩項處理措施,其中一項害了非洲
中國發明了一項處理核廢料技術,美國:要是早研製出來多好啊!我們的錢就不用白花了
士兵做不喜歡的一項處罰是什麼?新兵:5公里!老兵:蹲姿!
士兵犯錯後,最不堪回首的一項處罰,這滋味,回味無窮!
美國的犯罪分子不怕死,唯獨卻怕監獄裡的這項處罰?的確很痛苦!
首秀型球王!洛薩諾坐擁9項處子秀即進球紀錄