單擊鼠標中鍵(又名:鼠標滾輪),然後稍微向下移動鼠標可讓用戶在IE和大多數Windows應用程序中滾動。這種行爲默認情況下在WPF控件中缺失?有沒有一種設置,解決方法,或者我失蹤的東西顯而易見?如何讓WPF ScrollViewer中鍵單擊滾動?
回答
我發現如何使用3個鼠標事件(MouseDown
,MouseUp
,MouseMove
)來實現此目的。他們的處理程序連接到ScrollViewer
元素在下面的XAML:
<Grid>
<ScrollViewer MouseDown="ScrollViewer_MouseDown" MouseUp="ScrollViewer_MouseUp" MouseMove="ScrollViewer_MouseMove">
<StackPanel x:Name="dynamicLongStackPanel">
</StackPanel>
</ScrollViewer>
<Canvas x:Name="topLayer" IsHitTestVisible="False" />
</Grid>
倒不如寫一個行爲,而不是在代碼隱藏事件,但並不是每個人都有必要的圖書館,也是我不知道如何將它與Canvas
連接起來。
事件處理程序:
private bool isMoving = false; //False - ignore mouse movements and don't scroll
private bool isDeferredMovingStarted = false; //True - Mouse down -> Mouse up without moving -> Move; False - Mouse down -> Move
private Point? startPosition = null;
private double slowdown = 200; //The number 200 is found from experiments, it should be corrected
private void ScrollViewer_MouseDown(object sender, MouseButtonEventArgs e)
{
if (this.isMoving == true) //Moving with a released wheel and pressing a button
this.CancelScrolling();
else if (e.ChangedButton == MouseButton.Middle && e.ButtonState == MouseButtonState.Pressed)
{
if (this.isMoving == false) //Pressing a wheel the first time
{
this.isMoving = true;
this.startPosition = e.GetPosition(sender as IInputElement);
this.isDeferredMovingStarted = true; //the default value is true until the opposite value is set
this.AddScrollSign(e.GetPosition(this.topLayer).X, e.GetPosition(this.topLayer).Y);
}
}
}
private void ScrollViewer_MouseUp(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Middle && e.ButtonState == MouseButtonState.Released && this.isDeferredMovingStarted != true)
this.CancelScrolling();
}
private void CancelScrolling()
{
this.isMoving = false;
this.startPosition = null;
this.isDeferredMovingStarted = false;
this.RemoveScrollSign();
}
private void ScrollViewer_MouseMove(object sender, MouseEventArgs e)
{
var sv = sender as ScrollViewer;
if (this.isMoving && sv != null)
{
this.isDeferredMovingStarted = false; //standard scrolling (Mouse down -> Move)
var currentPosition = e.GetPosition(sv);
var offset = currentPosition - startPosition.Value;
offset.Y /= slowdown;
offset.X /= slowdown;
//if(Math.Abs(offset.Y) > 25.0/slowdown) //Some kind of a dead space, uncomment if it is neccessary
sv.ScrollToVerticalOffset(sv.VerticalOffset + offset.Y);
sv.ScrollToHorizontalOffset(sv.HorizontalOffset + offset.X);
}
}
如果去除方法調用AddScrollSign
和RemoveScrollSign
這個例子會工作。圖標
private void AddScrollSign(double x, double y)
{
int size = 50;
var img = new BitmapImage(new Uri(@"d:\middle_button_scroll.png"));
var adorner = new Image() { Source = img, Width = size, Height = size };
//var adorner = new Ellipse { Stroke = Brushes.Red, StrokeThickness = 2.0, Width = 20, Height = 20 };
this.topLayer.Children.Add(adorner);
Canvas.SetLeft(adorner, x - size/2);
Canvas.SetTop(adorner, y - size/2);
}
private void RemoveScrollSign()
{
this.topLayer.Children.Clear();
}
例:
而且最後一句話:但我有2種方法,其設置滾動圖標擴展它有一些問題的方式Press -> Immediately Release -> Move
。如果用戶單擊鼠標左鍵或鍵盤的任何鍵,或者應用程序失去焦點,它應該取消滾動。有很多事件,我沒有時間處理它們。
但標準方式Press -> Move -> Release
工作沒有問題。
+1爲解決方案,我雖然有一些建議,請看我的單獨的答案 – 2011-03-28 12:05:49
vorrtex發佈了一個很好的解決方案,請upvote他!
雖然我對他的解決方案有一些建議,但這些建議太冗長以至於無法將它們全部納入評論中,這就是爲什麼我發佈了一個單獨的答案並將其指引給他!
您提到了Press-> Release-> Move的問題。即使鼠標不在ScrollViewer上,您也應該使用MouseCapturing來獲取MouseEvents。我沒有測試過它,但我想你的解決方案在Press->Move->Move outside of ScrollViewer->Release
也失敗了,鼠標捕捉也會照顧到這一點。
你也提到使用行爲。我寧願建議一個不需要額外依賴的attached behavior。
你應該明確不使用額外的畫布,但在一個裝飾者中這樣做。
ScrollViewer自己擁有一個定義AdornerLayer的ScrollContentPresenter。你應該在那裏插入Adorner。這消除了對任何進一步依賴的需求,並且還保持了附加的行爲,如IsMiddleScrollable="true"
一樣簡單。
MouseCapture並不難實現,我會在幾個小時後這樣做。但其他評論並不那麼清楚。如果我使用附加屬性或行爲 - 我將無法將滾動圖像添加到「畫布」。另一方面'ScrollContentPresenter'控件位於'ScrollViewer'的模板中,我認爲我必須創建一個繼承的控件來訪問內部部件。我會盡力做到這一點,但我不確定新控件是否比一組事件處理程序更好。 – vorrtex 2011-03-28 14:57:51
鼠標捕獲MouseMove事件後只被調用一次。我必須創建一個計時器來觸發移動功能的方法。一切都變得越來越複雜。 – vorrtex 2011-03-29 08:51:55
@vorrtex明天晚上我會有時間的。正如我對一個不錯的緊湊型解決方案也很感興趣,我會深入探討它! – 2011-03-29 08:55:26
- 1. 中鍵單擊滾動
- 2. 設置何時滾動WPF ScrollViewer
- 3. ScrollViewer無法在WPF中滾動
- 4. 防止ScrollViewer滾動
- 5. WPF:如何以編程方式從ScrollViewer中提取滾動條?
- 6. 如何增加WPF ScrollViewer中的滾動條寬度?
- 7. wpf - 我該如何測試scrollviewer中的滾動條?
- 8. WPF ScrollViewer:水平滾動不起作用
- 9. WPF的ScrollViewer不會滾動起來
- 10. WPF XAML的ScrollViewer不會滾動
- 11. WPF ScrollViewer不能縱向滾動
- 12. C#/ WPF - 獲取ScrollViewer的滾動位置?
- 13. WPF Scrollviewer滾動到鼠標位置
- 14. ScrollViewer不滾動
- 15. 如何點擊WPF ScrollViewer向下按鈕
- 16. 無法讓WPF ScrollViewer工作
- 17. ScrollViewer不滾動
- 18. ScrollViewer不滾動
- 19. wp7,如何在ScrollViewer中阻止滾動
- 20. 如何將WPF ScrollViewer的內容滾動到特定位置
- 21. 如何使scrollviewer滾動像素不是組件(wpf)
- 22. 鎖定ScrollViewer中的滾動?
- 23. 如何讓我的ScrollViewer滾動查看區域?
- 24. 在ScrollViewer中滾動位置?
- 25. ScrollViewer與itemscontrol邏輯滾動
- 26. scrollviewer裏面的listview防止scrollviewer滾動
- 27. ScrollViewer水平鼠標滾輪滾動
- 28. ScrollViewer中的Safari-Like滾動條
- 29. 單擊並拖動使用的ScrollViewer
- 30. WPF的ListView ScrollViewer中雙擊事件
它可以處理鼠標中鍵事件:http://stackoverflow.com/questions/517556/how-to-handle-the-mouse-wheel-click-event-in-wpf。我會嘗試使用tomorow來正確處理和處理這個事件。 – vorrtex 2011-03-25 22:44:49