Frage

Ich habe eine Usercontrol, die einen Scroll hat, dann eine Reihe von untergeordneten Steuerelemente wie Textfelder, Optionsfelder und Listboxen, etc. im Inneren. Ich kann mit dem Mausrad die Eltern Scroll scrollen, bis die Maus in einem listbox dann landet die Mausradereignisse in das Listenfeld auf Start. gibt es eine Möglichkeit, die listbox senden diese Ereignisse an die übergeordnete Steuerelement sichern haben? das Listenfeld von innen Seite zu entfernen schlägt die übergeordnete Steuerung wie diese Frage (

War es hilfreich?

Lösung

Die Antwort, die Sie verwiesen haben, ist genau das, was Ihr Problem verursacht, die List-Box in Ihrem Scroll fängt das Mousewheel-Ereignis und Griffe es (was unter anderem eines Scrollzusammengesetzt ist), verhindert, dass es sprudelt und damit die Scroll hat keine Idee das Ereignis aufgetreten ist eh und je.

Mit der folgenden extrem einfach Control für Ihre List-Box zu zeigen (man beachte es keine Scroll hat in ihm und so das Mousewheel-Ereignis wird nicht gefangen werden) Die Scroll wird noch blättern mit der Maus über die List-Box.

<UserControl.Resources>
     <ControlTemplate x:Key="NoScroll">
         <ItemsPresenter></ItemsPresenter>
     </ControlTemplate>
</UserControl.Resources>

<ScrollViewer>
    <SomeContainerControl>
        <.... what ever other controls are inside your ScrollViewer>
        <ListBox Template="{StaticResource NoScroll}"></ListBox>
    <SomeContainerControl>
</ScrollViewer>

Sie haben die Möglichkeit, die Erfassung der Maus, wenn es die Scroll tritt aber so sie alle Mausereignisse empfangen wird fortgesetzt, bis die Maustaste losgelassen wird, aber diese Option würden Sie benötigen, um den innerhalb der enthaltenen Steuerelemente weitere Mausereignisse delgate Scroll wenn Sie eine Antwort wollen ... die folgenden MouseEnter- Leave Ereignishandler ausreichen wird.

private void ScrollViewerMouseEnter(object sender, MouseEventArgs e)
{
    ((ScrollViewer)sender).CaptureMouse();
}

private void ScrollViewerMouseLeave(object sender, MouseEventArgs e)
{
    ((ScrollViewer)sender).ReleaseMouseCapture();
}

Weder der Abhilfen I zur Verfügung gestellt haben, sind wirklich jedoch bevorzugt, und ich würde vorschlagen, zu überdenken, was Sie versuchen tatsächlich zu tun. Wenn Sie erklären, was Sie in Ihrer Frage zu erreichen versuchen bin ich sicher, dass Sie etwas mehr Vorschläge ...

Andere Tipps

Dies kann über angebrachtes Verhalten erreicht werden.

http://josheinstein.com /blog/index.php/2010/08/wpf-nested-scrollviewer-listbox-scrolling/

Edit: Hier ist die Lösung verknüpft:

  

„Anstatt also kam ich mit dem folgende IgnoreMouseWheelBehavior. Technisch bis es nicht das Mausrad zu ignorieren, aber es ist‚Weiterleitung‘die Veranstaltung wieder nach oben und aus der List-Box. Check it.“

/// <summary>
/// Captures and eats MouseWheel events so that a nested ListBox does not
/// prevent an outer scrollable control from scrolling.
/// </summary>
public sealed class IgnoreMouseWheelBehavior : Behavior<UIElement>
{

  protected override void OnAttached( )
  {
     base.OnAttached( );
      AssociatedObject.PreviewMouseWheel += AssociatedObject_PreviewMouseWheel ;
  }

  protected override void OnDetaching( )
  {
      AssociatedObject.PreviewMouseWheel -= AssociatedObject_PreviewMouseWheel;
      base.OnDetaching( );
  }

  void AssociatedObject_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
  {

      e.Handled = true;

      var e2 = new MouseWheelEventArgs(e.MouseDevice,e.Timestamp,e.Delta);
      e2.RoutedEvent = UIElement.MouseWheelEvent;

      AssociatedObject.RaiseEvent(e2);

  }

}
  

Und hier ist, wie Sie es in XAML verwenden würden.

<ScrollViewer Name="IScroll">
    <ListBox Name="IDont">
        <i:Interaction.Behaviors>
            <local:IgnoreMouseWheelBehavior />
        </i:Interaction.Behaviors>
    </ListBox>
</ScrollViewer>

Wenn der i-Namensraum ist von Blend:

 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

Ich folgte Amanduh Ansatz das gleiche Problem zu lösen ich mit mehreren Datagrids in einem Scroll hatte aber in WPF:

public sealed class IgnoreMouseWheelBehavior 
{
    public static bool GetIgnoreMouseWheel(DataGrid gridItem)
    {
        return (bool)gridItem.GetValue(IgnoreMouseWheelProperty);
    }

    public static void SetIgnoreMouseWheel(DataGrid gridItem, bool value)
    {
        gridItem.SetValue(IgnoreMouseWheelProperty, value);
    }

    public static readonly DependencyProperty IgnoreMouseWheelProperty =
        DependencyProperty.RegisterAttached("IgnoreMouseWheel", typeof(bool),
        typeof(IgnoreMouseWheelBehavior), new UIPropertyMetadata(false, OnIgnoreMouseWheelChanged));

    static void OnIgnoreMouseWheelChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        var item = depObj as DataGrid;
        if (item == null)
            return;

        if (e.NewValue is bool == false)
            return;

        if ((bool)e.NewValue)
            item.PreviewMouseWheel += OnPreviewMouseWheel;
        else
            item.PreviewMouseWheel -= OnPreviewMouseWheel;
    }

    static void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        e.Handled = true;

        var e2 = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
                     {RoutedEvent = UIElement.MouseWheelEvent};

        var gv = sender as DataGrid;
        if (gv != null) gv.RaiseEvent(e2);
    }
}

, sagte Simon, es ist die Scroll in der Standard-List-Box-Vorlage, die das Ereignis ist ansteckend. Um Bypass es können Sie Ihre eigene Vorlage zur Verfügung stellen.

<ControlTemplate x:Key="NoWheelScrollListBoxTemplate" TargetType="ListBox">
    <Border BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="1,1,1,1" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" Name="Bd" SnapsToDevicePixels="True">
        <!-- This is the new control -->
        <l:NoWheelScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False">
            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
        </l:NoWheelScrollViewer>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="UIElement.IsEnabled" Value="False">
            <Setter TargetName="Bd" Property="Panel.Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
        </Trigger>
        <Trigger Property="ItemsControl.IsGrouping" Value="True">
            <Setter Property="ScrollViewer.CanContentScroll" Value="False" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

Und die Umsetzung für NoWheelScrollViewer ist ziemlich einfach.

public class NoWheelScrollViewer : ScrollViewer
{
    protected override void OnMouseWheel(MouseWheelEventArgs e)
    {
        // Do nothing
    }
}

Dann, wenn Sie einen listbox wollen nicht das Mausrad behandeln.

<ListBox Template="{StaticResource NoWheelScrollListBoxTemplate}">

Eine einfache Lösung, die für mich gearbeitet ist, um die innere Steuervorlage außer Kraft zu setzen, den Scroll-Viewer (je nachdem, was erforderlich) wie diese

entfernen

Zum Beispiel Ich habe eine Struktur wie diese

  • Listview (a)

    • Listview (b)

      • Listview (c)

ich Blase wollte das Mausrad Scroll von (b) (a), jedoch wollte das Mausrad Scroll von (c) zur Verfügung halten. Ich habe einfach die Vorlage von (b) wie folgt überschrieben. Das erlaubte mir, zu sprudeln Inhalt von (b) mit Ausnahme von (c) (a). Auch kann ich blättern noch den Inhalt (c). Wenn ich auch für (c) entfernen möchten, dann muss ich den gleichen Schritt wiederholen.

<ListView.Template>
  <ControlTemplate>
     <ItemsPresenter />
  </ControlTemplate>
</ListView.Template>

Ich habe versucht, Simon Fox Antwort für einen Datagrid anzupassen. Ich fand das die Vorlage meine Header verborgen, und ich habe nie die mouseleave Veranstaltung, indem sie es in C # zu tun. Dies ist letztlich das, was für mich gearbeitet:

    private void DataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        ((DataGrid)sender).CaptureMouse();
    }

    private void DataGrid_MouseWheel(object sender, MouseWheelEventArgs e)
    {
        ((DataGrid)sender).ReleaseMouseCapture();
    }

Eine modifizierte Simon Fox-Lösung, wenn das Original nicht funktioniert:

public sealed class IgnoreMouseWheelBehavior : Behavior<UIElement>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.PreviewMouseWheel += AssociatedObject_PreviewMouseWheel;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.PreviewMouseWheel -= AssociatedObject_PreviewMouseWheel;
        base.OnDetaching();
    }

    static void AssociatedObject_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (!(sender is DependencyObject))
        {
            return;
        }

        DependencyObject parent = VisualTreeHelper.GetParent((DependencyObject) sender);
        if (!(parent is UIElement))
        {
            return;
        }

        ((UIElement) parent).RaiseEvent(
            new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta) { RoutedEvent = UIElement.MouseWheelEvent });
        e.Handled = true;
    }
}

Sie müssen Preview von Scroll hören (es funktioniert), aber nicht von listbox.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top