Wie können Sie eine Datagridview Scroll ein Element zu einem Zeitpunkt machen mit dem Mausrad?
-
02-07-2019 - |
Frage
Wir möchten Datagridview Standardverhalten außer Kraft zu setzen, wenn ein Mausrad mit dieser Steuerung. Standardmäßig entspricht die Datagridview scrollt eine Anzahl von Zeilen der SystemInformation.MouseWheelScrollLines Einstellung. Was wir möchten, dass tun, scroll nur ein Element zu einem Zeitpunkt.
(Wir zeigen Bilder in der Datagridview, die etwas groß ist. Aufgrund dieser Scroll drei Reihen (eine typische Systemeinstellung) ist zu viel, oft den Benutzer verursacht, um Elemente zu blättern sie nicht einmal sehen können.)
Ich habe schon ein paar Dinge ausprobiert und haben nicht viel Erfolg bisher hatte. Hier sind einige Fragen, die ich habe laufen in:
-
Sie können Mousewheel Ereignisse abonnieren, aber es gibt keine Möglichkeit, das Ereignis als behandelt zu markieren und mein eigenes Ding machen.
-
Sie können OnMouseWheel außer Kraft setzen, aber dies scheint nicht aufgerufen werden.
-
Sie könnten in der Lage sein, diese Scroll-Code in der Basis zu korrigieren, aber es klingt wie eine schmutzige Arbeit, da andere Arten von Scrollen (z.B. die Tastatur) kommt durch die gleiche Pipeline.
Wer einen guten Vorschlag?
Hier ist der endgültige Code, die wunderbare Antwort mit angegeben:
/// <summary>
/// Handle the mouse wheel manually due to the fact that we display
/// images, which don't work well when you scroll by more than one
/// item at a time.
/// </summary>
///
/// <param name="sender">
/// sender
/// </param>
/// <param name="e">
/// the mouse event
/// </param>
private void mImageDataGrid_MouseWheel(object sender, MouseEventArgs e)
{
// Hack alert! Through reflection, we know that the passed
// in event argument is actually a handled mouse event argument,
// allowing us to handle this event ourselves.
// See http://tinyurl.com/54o7lc for more info.
HandledMouseEventArgs handledE = (HandledMouseEventArgs) e;
handledE.Handled = true;
// Do the scrolling manually. Move just one row at a time.
int rowIndex = mImageDataGrid.FirstDisplayedScrollingRowIndex;
mImageDataGrid.FirstDisplayedScrollingRowIndex =
e.Delta < 0 ?
Math.Min(rowIndex + 1, mImageDataGrid.RowCount - 1):
Math.Max(rowIndex - 1, 0);
}
Lösung
Ich habe gerade ein wenig schnorren und Prüfung von meinem eigenen. Ich benutzte Reflector zu untersuchen und ein paar Dinge entdeckt. Das MouseWheel
Ereignis stellt einen MouseEventArgs
Parameter, aber die OnMouseWheel()
Überschreibung in DataGridView
wirft es auf Handled
MouseEventArgs
. Dies funktioniert auch, wenn die MouseWheel
Event-Handling. OnMouseWheel()
in der Tat aufgerufen, und es ist in Überschreibung DataGridView
ist, dass es SystemInformation.MouseWheelScrollLines
verwendet.
So:
-
Sie in der Tat das
MouseWheel
Ereignis umgehen können,MouseEventArgs
GießenHandledMouseEventArgs
und setztHandled = true
, dann tun, was Sie wollen. -
Subclass
DataGridView
gekröpftOnMouseWheel()
selbst, und versuchen, den gesamten Code erstellen Ich lese hier in Reflector AusnahmeSystemInformation.MouseWheelScrollLines
mit1
ersetzt werden.
Letzteres wäre ein großer Schmerz sein, weil es eine Reihe von privaten Variablen verwendet (einschließlich Verweise auf den ScrollBar
s) und Sie würden einige mit Ihrem eigenen haben ersetzen und erhalten / set andere Reflexion verwendet wird.
Andere Tipps
würde ich das Datagridview in meine eigene benutzerdefinierte Steuerunterklasse (Sie wissen schon, fügen Sie eine neue Windows Forms -> Datei Custom Control und die Basisklasse von Control Datagridview aus)
.public partial class MyDataGridView : DataGridView
Dann überschreiben Sie die WndProc Methode und Ersatz etwas wie folgt:
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x20a)
{
int wheelDelta = ((int)m.WParam) >> 16;
// 120 = UP 1 tick
// -120 = DOWN 1 tick
this.FirstDisplayedScrollingRowIndex -= (wheelDelta / 120);
}
else
{
base.WndProc(ref m);
}
}
Natürlich, werden Sie die Kontrolle haben, dass Sie nicht setzen FirstDisplayedScrollingRowIndex auf eine Zahl außerhalb des Bereichs des Rasters etc. Aber das funktioniert ganz gut!
Richard
Übergeordnete OnMouseWheel und nicht Aufruf base.OnMouseWheel funktionieren soll. Einige Rad Mäuse haben spezielle Einstellungen, die Sie benötigen, sich zu setzen, damit sie richtig arbeiten. Sehen Sie diesen Beitrag http://forums.microsoft.com/MSDN/ShowPost aspx? PostID = 126295 & SiteID = 1
UPDATE: Da ich jetzt habe gelernt, dass die DataGridView
ein MouseWheel
Ereignis hat, habe ich eine zweite, einfachere Überschreibung hinzugefügt
Eine Möglichkeit, dies zu erreichen, ist die DataGridView
Unterklasse und die WndProc
außer Kraft setzt spezielle Handhabung der WM_MOUSEWHEEL
Nachricht hinzuzufügen.
In diesem Beispiel fängt die Mausrad Bewegung und ersetzt sie durch einen Aufruf SendKeys.Send
.
(Dies ist ein wenig anders als nur Scrollen, da sie auch die nächste / vorherige Zeile des DataGridView
wählt. Aber es funktioniert.)
public class MyDataGridView : DataGridView
{
private const uint WM_MOUSEWHEEL = 0x20a;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOUSEWHEEL)
{
var wheelDelta = ((int)m.WParam) >> 16;
if (wheelDelta < 0)
{
SendKeys.Send("{DOWN}");
}
if (wheelDelta > 0)
{
SendKeys.Send("{UP}");
}
return;
}
base.WndProc(ref m);
}
}
2. nehmen (mit den gleichen Einschränkungen wie oben erwähnt):
public class MyDataGridView : DataGridView
{
protected override void OnMouseWheel(MouseEventArgs e)
{
if (e.Delta < 0)
SendKeys.Send("{DOWN}");
else
SendKeys.Send("{UP}");
}
}