我有一個控件動態添加到面板的窗體。但是,當它們這樣做時,它們會多次添加到摺疊下方(容器的底部)。很高興.NET Framework提供了這個ScrollControlIntoView方法,但是,爲了增加可用性,如果有一種簡單的動畫方法,以便用戶很容易理解Panel自動滾動,這也會很不錯。有沒有簡單的方法來動畫ScrollableControl.ScrollControlIntoView方法?
有沒有人遇到過這個問題,或者對於如何解決它有什麼想法?
我有一個控件動態添加到面板的窗體。但是,當它們這樣做時,它們會多次添加到摺疊下方(容器的底部)。很高興.NET Framework提供了這個ScrollControlIntoView方法,但是,爲了增加可用性,如果有一種簡單的動畫方法,以便用戶很容易理解Panel自動滾動,這也會很不錯。有沒有簡單的方法來動畫ScrollableControl.ScrollControlIntoView方法?
有沒有人遇到過這個問題,或者對於如何解決它有什麼想法?
您可以子類Panel
,添加Timer
,並覆蓋ScrollIntoView()
,以便在新的AnimatedScrollPanel
中執行此操作。我很肯定你必須這樣做才能使用某些protected
方法,例如ScrollToControl()
,它會返回Point
(由ScrollIntoView
使用)。
@Joel
謝謝!我明白了,用反射鏡的幫助並不難。可能有方法來優化它,但這是我必須開始的。恰巧我需要FlowLayoutPanel中的這個功能,但它可以處理從ScrollableControl繼承的任何東西。
編輯:我改變了一些東西,由於@Joel B指出我沒有刪除委託,保持定時器對象無限期。我相信我通過將委託分配給一個EventHandler對象來緩解這種擔憂,以便它可以在其內部被移除。
using System;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
public class AnimatedScrollFlowLayoutPanel : FlowLayoutPanel
{
public new void ScrollControlIntoView(Control activeControl)
{
if (((this.IsDescendant(activeControl) && this.AutoScroll) &&
(this.HScroll || this.VScroll)) && (((activeControl != null) &&
(ClientRectangle.Width > 0)) && (ClientRectangle.Height > 0)))
{
Point point = this.ScrollToControl(activeControl);
int x = DisplayRectangle.X, y = DisplayRectangle.Y;
bool scrollUp = x < point.Y;
bool scrollLeft = y < point.X;
Timer timer = new Timer();
EventHandler tickHandler = null;
tickHandler = delegate {
int jumpInterval = ClientRectangle.Height/10;
if (x != point.X || y != point.Y)
{
y = scrollUp ?
Math.Min(point.Y, y + jumpInterval) :
Math.Max(point.Y, y - jumpInterval);
x = scrollLeft ?
Math.Min(point.X, x + jumpInterval) :
Math.Max(point.X, x - jumpInterval);
this.SetScrollState(8, false);
this.SetDisplayRectLocation(x, y);
this.SyncScrollbars(true);
}
else
{
timer.Stop();
timer.Tick -= tickHandler;
}
};
timer.Tick += tickHandler;
timer.Interval = 5;
timer.Start();
}
}
internal bool IsDescendant(Control descendant)
{
MethodInfo isDescendantMethod = typeof(Control).GetMethod(
"IsDescendant", BindingFlags.NonPublic | BindingFlags.Instance);
return (bool)isDescendantMethod.Invoke(this, new object[] { descendant });
}
private void SyncScrollbars(bool autoScroll)
{
MethodInfo syncScrollbarsMethod = typeof(ScrollableControl).GetMethod(
"SyncScrollbars", BindingFlags.NonPublic | BindingFlags.Instance);
syncScrollbarsMethod.Invoke(this, new object[] { autoScroll });
}
}
有一個大問題。您不斷將代理添加到Tick事件中,並且在完成時不要刪除它。您需要重新設計一下,以便您一次只能在Tick事件中擁有1個代表。 – 2008-10-07 14:58:21