簡體   English   中英

MVVM WPF中的ListBox滾動事件

[英]ListBox scrolling event in MVVM WPF

有沒有辦法以MVVM方式在WPF(Windows Phone7)中掛接滾動事件? 我想檢測列表何時滾動到底部,然后執行某些操作。 我嘗試過類似的方法,但顯然不起作用:

<ListBox ItemsSource="{Binding Places}" SelectedItem="{Binding SelectedPlace, Mode=TwoWay}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Tap">
            <i:InvokeCommandAction Command="{Binding ListBoxClick}"/>
        </i:EventTrigger>
        <i:EventTrigger EventName="Scroll">
            <i:InvokeCommandAction Command="{Binding ListBoxScroll}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    (...)
</ListBox>

在這種情況下,我總是朝着附加行為的方向看,因為我們需要一個可以在側面UI和MVVM風格上運行的獨立解決方案。 附加行為-是附加屬性,它具有事件處理程序來更改此屬性,並且所有邏輯都在該處理程序中實現。

在這種情況下,您需要傳遞一個布爾值,該值指示行為的開始以及命令(執行條件時執行的命令)-滾動到ListBox的末尾。

我創建了一個示例行為,其中的關鍵邏輯在這里:

private static void scrollViewerScrollChanged(object sender, ScrollChangedEventArgs e)
{
    var scrollViewer = sender as ScrollViewer;

    if (scrollViewer != null)
    {
        // Here we determine if the bottom reached
        if (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight)
        {
            command = GetCommand(listBox);

            // Execute the command
            command.Execute(listBox);
        }
    }
}

使用示例:

XAML

<Window.DataContext>
    <local:TestViewModel />
</Window.DataContext>

<Window.Resources>
    <x:Array x:Key="TestArray" Type="{x:Type sys:String}">
        <sys:String>Test1</sys:String>
        <sys:String>Test2</sys:String>
        <sys:String>Test3</sys:String>
        <sys:String>Test4</sys:String>
        <sys:String>Test5</sys:String>
        <sys:String>Test6</sys:String>
        <sys:String>Test7</sys:String>
        <sys:String>Test8</sys:String>
        <sys:String>Test9</sys:String>
        <sys:String>Test10</sys:String>
    </x:Array>
</Window.Resources>

<Grid>
    <ListBox Name="TestListBox"
             AttachedBehaviors:ScrollingToBottomBehavior.IsEnabled="True"
             AttachedBehaviors:ScrollingToBottomBehavior.Command="{Binding TestButtonCommand}"
             ItemsSource="{StaticResource TestArray}"
             Height="50" />
</Grid>

TestViewModel

public class TestViewModel
{
    private ICommand _testButtonCommand = null;

    public ICommand TestButtonCommand
    {
        get
        {
            if (_testButtonCommand == null)
            {
                _testButtonCommand = new RelayCommand(param => this.TestButton(), null);
            }

            return _testButtonCommand;
        }
    }

    private void TestButton()
    {
        MessageBox.Show("Test command execute");
    }
}

ScrollingToBottomBehavior

public class ScrollingToBottomBehavior
{
    #region Private Section

    private static ListBox listBox = null;
    private static ICommand command = null;

    #endregion

    #region IsEnabledProperty

    public static readonly DependencyProperty IsEnabledProperty;

    public static void SetIsEnabled(DependencyObject DepObject, string value)
    {
        DepObject.SetValue(IsEnabledProperty, value);
    }

    public static bool GetIsEnabled(DependencyObject DepObject)
    {
        return (bool)DepObject.GetValue(IsEnabledProperty);
    }

    #endregion

    #region CommandProperty

    public static readonly DependencyProperty CommandProperty;

    public static void SetCommand(DependencyObject DepObject, ICommand value)
    {
        DepObject.SetValue(CommandProperty, value);
    }

    public static ICommand GetCommand(DependencyObject DepObject)
    {
        return (ICommand)DepObject.GetValue(CommandProperty);
    }

    static ScrollingToBottomBehavior()
    {
        IsEnabledProperty = DependencyProperty.RegisterAttached("IsEnabled",
                                                            typeof(bool),
                                                            typeof(ScrollingToBottomBehavior),
                                                            new UIPropertyMetadata(false, IsFrontTurn));

        CommandProperty = DependencyProperty.RegisterAttached("Command",
                                                            typeof(ICommand),
                                                            typeof(ScrollingToBottomBehavior));
    }

    #endregion

    private static void IsFrontTurn(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        listBox = sender as ListBox;

        if (listBox == null)
        {
            return;
        }

        if (e.NewValue is bool && ((bool)e.NewValue) == true)
        {
            listBox.Loaded += new RoutedEventHandler(listBoxLoaded);
        }
        else 
        {
            listBox.Loaded -= new RoutedEventHandler(listBoxLoaded);
        }
    }

    private static void listBoxLoaded(object sender, RoutedEventArgs e)
    {
        var scrollViewer = GetFirstChildOfType<ScrollViewer>(listBox);

        if (scrollViewer != null)
        {
            scrollViewer.ScrollChanged += new ScrollChangedEventHandler(scrollViewerScrollChanged);
        }
    }

    #region GetFirstChildOfType

    private static T GetFirstChildOfType<T>(DependencyObject dependencyObject) where T : DependencyObject
    {
        if (dependencyObject == null)
        {
            return null;
        }

        for (var i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++)
        {
            var child = VisualTreeHelper.GetChild(dependencyObject, i);

            var result = (child as T) ?? GetFirstChildOfType<T>(child);

            if (result != null)
            {
                return result;
            }
        }

        return null;
    }

    #endregion

    private static void scrollViewerScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        var scrollViewer = sender as ScrollViewer;

        if (scrollViewer != null)
        {
            if (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight)
            {
                command = GetCommand(listBox);
                command.Execute(listBox);
            }
        }
    }
}

完整的示例項目可here

暫無
暫無

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

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