簡體   English   中英

如何在 ListBox 中禁用 ScrollViewer?

[英]How to disable ScrollViewer in ListBox?

我有一個列表框。 它具有內部 ScrollViewer,因此我可以使用鼠標滾輪滾動 ListBox 內容。 它工作正常,直到我設置包含另一個 ListBox 的項目模板(實際上,我有 4 個嵌套的 ListBoxes =))。 問題是內部 ListBox 的 ScrollViewer 竊取了輪動事件。 有什么簡單的方法可以防止這種行為嗎?


我有像這樣的帶有 ItemContainerStyle 的 ListBox:

<Style x:Key="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
    <Setter Property="BorderBrush" Value="Black"/>
     ... 
</Style>
<ListBox ItemContainerStyle="{StaticResource ListBoxItemStyle}" />

如何在這樣的資源中為 ItemContainer 的項目邊框設置樣式? 據我所知,ContentPresenter 是 ItemsControl 的項目容器。 但它沒有邊框,所以我無法設計它。

您可以通過將其控件模板更改為更簡單的內容來從ListBox刪除ScrollViewer

<ListBox>
    <ListBox.Template>
        <ControlTemplate>
            <ItemsPresenter />
        </ControlTemplate>
    </ListBox.Template>
    ...
</ListBox>

但是,我質疑嵌套 ListBoxes 的價值。 請記住,每個ListBox都是一個 Selector,並且具有“選擇”哪個項目的概念。 在選定的項目中,在選定的項目中放置一個選定的項目真的有意義嗎?

我建議將“內部” ListBoxes更改為簡單的ItemsControls這樣嵌套列表就不能有選定的項目。 這將使用戶體驗更加簡單。 您可能仍然需要以相同的方式重新模板內部ItemsControls以刪除滾動條,但至少用戶不會對“選擇”哪個項目感到困惑。

您可以通過在 XAML 中捕獲滾動事件來禁用竊取滾動事件:

<ListBox PreviewMouseWheel="ScrollViewer_PreviewMouseWheel">

並在后面的代碼中重新發布它:

private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (sender is ListBox && !e.Handled)
        {
            e.Handled = true;
            var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
            eventArg.RoutedEvent = UIElement.MouseWheelEvent;
            eventArg.Source = sender;
            var parent = ((Control)sender).Parent as UIElement;
            parent.RaiseEvent(eventArg);
        }
    }

該解決方案完全適用於 ListBox,它幫助我使用了 ListView。

我在這里找到了這個解決方案:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/3a3bb6b0-e088-494d-8ef2-60814415fd89/swallowing-mouse-scroll?forum=wpf

很抱歉喚醒了這么一個舊帖子。 實際上,您可以使用 ScrollViewer 的附加屬性禁用 ScrollViewer。

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
         ScrollViewer.VerticalScrollBarVisibility="Disabled" ...
</ListBox>

我喜歡為這種類型的事情創建一個行為。

xmlns:bhv="http://schemas.microsoft.com/xaml/behaviors"

<ListView ItemsSource="{Binding Items}">
    <bhv:Interaction.Behaviors>
        <bhvs:NoScrollingBehavior/>
    </bhv:Interaction.Behaviors>
</ListView>

行為本身。

public class NoScrollingBehavior : Behavior<UIElement>
{
    public NoScrollingBehavior()
    { }

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

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

    private void PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        e.Handled = true;
        var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
        eventArg.RoutedEvent = UIElement.MouseWheelEvent;
        eventArg.Source = sender;
        var parent = ((Control)sender).Parent as UIElement;
        parent.RaiseEvent(eventArg);
    }
}

如果您不喜歡行為,這里有一個帶有 DependencyProperty 的變體

public class IgnoreScrollingBehavior
{
    public static readonly DependencyProperty IgnoreScrollingProperty =
        DependencyProperty.RegisterAttached("IgnoreScrolling", typeof(bool),
            typeof(IgnoreScrollingBehavior), new UIPropertyMetadata(false, OnIgnoreScrollingChanged));

    public static bool GetIgnoreScrolling(UIElement uIElement)
    {
        return (bool)uIElement.GetValue(IgnoreScrollingProperty);
    }

    public static void SetIgnoreScrolling(UIElement uIElement, bool value)
    {
        uIElement.SetValue(IgnoreScrollingProperty, value);
    }

    private static void OnIgnoreScrollingChanged(DependencyObject depOpj, DependencyPropertyChangedEventArgs e)
    {
        if (depOpj is not UIElement item)
        {
            return;
        }

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

    private static void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        e.Handled = true;
        MouseWheelEventArgs eventArg = new(e.MouseDevice, e.Timestamp, e.Delta)
        {
            RoutedEvent = UIElement.MouseWheelEvent,
            Source = sender
        };
        UIElement parent = ((Control)sender).Parent as UIElement;
        parent.RaiseEvent(eventArg);
    }
}

這是它的使用方式

<Listbox b:IgnoreScrollingBehavior.IgnoreScrolling="True".../>

你可以用這個! 沒有輪子被盜。

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
     ScrollViewer.VerticalScrollBarVisibility="Disabled" ...
</ListBox>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM