WPF Nested Scrollviewers - возвращение контроля родительскому scollviewer
Вот как выглядит мое дерево управления:
<window>
<scrollviewer>
<expander>
<scrollviewer>
<grid>
</grid>
</scrollviewer>
</expander>
<expander>
<scrollviewer>
<grid>
</grid>
</scrollviewer>
</expander>
</scrollviewer>
</window>
Используя колесо мыши, элемент управления автоматически переходит от родительского к дочернему scrollviewer, но когда я прокручиваю до конца дочернего scrollviewer, элемент управления не возвращается обратно к родительскому scorllviewer. Как мне этого добиться?
Расширитель, сетка и средства просмотра прокрутки генерируются динамически.
1 ответ
Я получаю аналогичные проблемы в моем приложении. Я исправляю это свойством зависимости, которое будет перехватывать и передавать событие его родителю. Это может быть применено к любому элементу управления, в котором есть прокрутка. Но мне не нужно было проверять, было ли это в конце свитка, чтобы отправить его родителю. Вам просто нужно добавить в метод OnValueChanged проверку того, находится ли свиток в конце или вверху для отправки его родителю.
using System.Windows.Controls;
public static class SendMouseWheelToParent
{
public static readonly DependencyProperty ScrollProperty
= DependencyProperty.RegisterAttached("IsSendingMouseWheelEventToParent",
typeof(bool),
typeof(SendMouseWheelToParent),
new FrameworkPropertyMetadata(OnValueChanged));
/// <summary>
/// Gets the IsSendingMouseWheelEventToParent for a given <see cref="TextBox"/>.
/// </summary>
/// <param name="control">
/// The <see cref="TextBox"/> whose IsSendingMouseWheelEventToParent is to be retrieved.
/// </param>
/// <returns>
/// The IsSendingMouseWheelEventToParent, or <see langword="null"/>
/// if no IsSendingMouseWheelEventToParent has been set.
/// </returns>
public static bool? GetIsSendingMouseWheelEventToParent(Control control)
{
if (control == null)
throw new ArgumentNullException("");
return control.GetValue(ScrollProperty) as bool?;
}
/// <summary>
/// Sets the IsSendingMouseWheelEventToParent for a given <see cref="TextBox"/>.
/// </summary>
/// <param name="control">
/// The <see cref="TextBox"/> whose IsSendingMouseWheelEventToParent is to be set.
/// </param>
/// <param name="IsSendingMouseWheelEventToParent">
/// The IsSendingMouseWheelEventToParent to set, or <see langword="null"/>
/// to remove any existing IsSendingMouseWheelEventToParent from <paramref name="control"/>.
/// </param>
public static void SetIsSendingMouseWheelEventToParent(Control control, bool? sendToParent)
{
if (control == null)
throw new ArgumentNullException("");
control.SetValue(ScrollProperty, sendToParent);
}
private static void OnValueChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var scrollViewer = dependencyObject as Control;
bool? IsSendingMouseWheelEventToParent = e.NewValue as bool?;
scrollViewer.PreviewMouseWheel -= scrollViewer_PreviewMouseWheel;
if (IsSendingMouseWheelEventToParent != null && IsSendingMouseWheelEventToParent != false)
{
scrollViewer.SetValue(ScrollProperty, IsSendingMouseWheelEventToParent);
scrollViewer.PreviewMouseWheel += scrollViewer_PreviewMouseWheel;
}
}
private static void scrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
var scrollview = sender as Control;
var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
eventArg.RoutedEvent = UIElement.MouseWheelEvent;
eventArg.Source = sender;
var parent = scrollview.Parent as UIElement;
parent.RaiseEvent(eventArg);
}
}
Вдохновленный ответом Яника и некоторыми другими, у меня есть реализация, которая прокручивает предки ScrollViewers, когда внутренние (в том числе из ListView, ListBox, DataGrid) прокручиваются мимо их верха / низа. Код находится в моем ответе на очень похожий вопрос.