[英]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.