-
框架使用 .NET40
; -
Visual Studio 2022
; -
后台选中数据后列表控件滚动到当前所在行的几种方法 -
1.可通过 Behavior
行为实现。 -
2.可通过附加属性去调用 ScrollIntoView
方法实现DataGrid
ListBox
ListView
滚动到视图。.
-
方式一
1)ScrollBehavior
实现如下:
-
找到 System.Windows.Interactivity.dll
文件并引入
public class ScrollBehavior : Behavior<ListBox>
{
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.SelectionChanged += new SelectionChangedEventHandler(AssociatedObject_SelectionChanged);
}
void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (sender is ListBox listBox)
{
if (listBox.SelectedItem != null)
{
listBox.Dispatcher.BeginInvoke((Action)delegate
{
listBox.UpdateLayout();
listBox.ScrollIntoView(listBox.SelectedItem);
});
}
}
}
protected override void OnDetaching()
{
base.OnDetaching();
this.AssociatedObject.SelectionChanged -= new SelectionChangedEventHandler(AssociatedObject_SelectionChanged);
}
}
2)Xaml
使用如下,即可完成跳转:
-
引入命名空间;
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
-
使用如下:
<ListBox HorizontalAlignment="Center" Margin="20">
<i:Interaction.Behaviors>
<local:ScrollBehavior/>
</i:Interaction.Behaviors>
</ListBox>
方式二
1)新建 ScrollIntoView
如下:
using System;
using System.Windows;
using System.Windows.Controls;
namespace WPFDevelopers.Helpers
{
public class ScrollIntoView
{
public static readonly DependencyProperty IsPositionProperty = DependencyProperty.RegisterAttached(
"IsPosition",
typeof(object),
typeof(ScrollIntoView),
new PropertyMetadata(default(object), OnIsPositionChanged));
public static object GetIsPosition(DependencyObject target)
{
return (object)target.GetValue(IsPositionProperty);
}
public static void SetIsPosition(DependencyObject target, object value)
{
target.SetValue(IsPositionProperty, value);
}
static void OnIsPositionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var type = sender.GetType();
switch (type)
{
case Type _ when type == typeof(DataGrid):
var dataGrid = (DataGrid)sender;
if (dataGrid == null)
return;
dataGrid.SelectionChanged += delegate
{
if (dataGrid.SelectedItem == null) return;
#if NET40
dataGrid.Dispatcher.BeginInvoke((Action)(() =>
{
dataGrid.UpdateLayout();
dataGrid.ScrollIntoView(dataGrid.SelectedItem, null);
}));
#else
dataGrid.Dispatcher.InvokeAsync(() =>
{
dataGrid.UpdateLayout();
dataGrid.ScrollIntoView(dataGrid.SelectedItem, null);
});
#endif
};
break;
case Type _ when type == typeof(ListBox):
var listBox = (ListBox)sender;
if (listBox == null)
return;
listBox.SelectionChanged += delegate
{
if (listBox.SelectedItem == null) return;
#if NET40
listBox.Dispatcher.BeginInvoke((Action)(() =>
{
listBox.UpdateLayout();
listBox.ScrollIntoView(listBox.SelectedItem);
}));
#else
listBox.Dispatcher.InvokeAsync(() =>
{
listBox.UpdateLayout();
listBox.ScrollIntoView(listBox.SelectedItem);
});
#endif
};
break;
case Type _ when type == typeof(ListView):
var listView = (ListView)sender;
if (listView == null)
return;
listView.SelectionChanged += delegate
{
if (listView.SelectedItem == null) return;
#if NET40
listView.Dispatcher.BeginInvoke((Action)(() =>
{
listView.UpdateLayout();
listView.ScrollIntoView(listView.SelectedItem);
}));
#else
listView.Dispatcher.InvokeAsync(() =>
{
listView.UpdateLayout();
listView.ScrollIntoView(listView.SelectedItem);
});
#endif
};
break;
default:
break;
}
}
}
}
2)SelectorExample.xaml
实例代码如下:
<UserControl x:Class="WPFDevelopers.Samples.ExampleViews.SelectorExample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
xmlns:vm="clr-namespace:WPFDevelopers.Samples.ViewModels"
xmlns:model="clr-namespace:WPFDevelopers.Sample.Models"
xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Margin="4">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="0,4"
HorizontalAlignment="Center">
<TextBox wd:ElementHelper.IsWatermark="True"
wd:ElementHelper.Watermark="输入数字0~199"
x:Name="MyTextBox"/>
<Button
Style="{StaticResource DangerPrimaryButton}"
Content="定位行"
Click="Button_Click"
Margin="4,0"/>
</StackPanel>
<UniformGrid Rows="2" Columns="2" Grid.Row="1">
<DataGrid ItemsSource="{Binding ListArrays,RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedItem="{Binding SelectItem,RelativeSource={RelativeSource AncestorType=UserControl}}"
wd:ScrollIntoView.IsPosition="true"
Margin="4" IsReadOnly="True">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn Header="Date" Binding="{Binding Date}" Width="Auto"/>
</DataGrid.Columns>
</DataGrid>
<ListBox ItemsSource="{Binding ListArrays,RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedItem="{Binding SelectItem,RelativeSource={RelativeSource AncestorType=UserControl}}"
wd:ScrollIntoView.IsPosition="true"
Margin="4">
<ListBox.ItemTemplate>
<DataTemplate>
<UniformGrid Columns="2">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Date}"/>
</UniformGrid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListView ItemsSource="{Binding ListArrays,RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedItem="{Binding SelectItem,RelativeSource={RelativeSource AncestorType=UserControl}}"
wd:ScrollIntoView.IsPosition="true"
Margin="4">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Date" DisplayMemberBinding="{Binding Date}" />
</GridView>
</ListView.View>
</ListView>
</UniformGrid>
</Grid>
</UserControl>
3)SelectorExample.xaml.cs
实例代码如下:
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
using System.Collections.ObjectModel;
using WPFDevelopers.Sample.Models;
using System;
using System.Linq;
namespace WPFDevelopers.Samples.ExampleViews
{
/// <summary>
/// SelectorExample.xaml 的交互逻辑
/// </summary>
public partial class SelectorExample : UserControl
{
public ObservableCollection<UserModel> ListArrays
{
get { return (ObservableCollection<UserModel>)GetValue(ListArraysProperty); }
set { SetValue(ListArraysProperty, value); }
}
public static readonly DependencyProperty ListArraysProperty =
DependencyProperty.Register("ListArrays", typeof(ObservableCollection<UserModel>), typeof(SelectorExample), new PropertyMetadata(null));
public UserModel SelectItem
{
get { return (UserModel)GetValue(SelectItemProperty); }
set { SetValue(SelectItemProperty, value); }
}
public static readonly DependencyProperty SelectItemProperty =
DependencyProperty.Register("SelectItem", typeof(UserModel), typeof(SelectorExample), new PropertyMetadata(null));
public SelectorExample()
{
InitializeComponent();
Loaded += SelectorExample_Loaded;
}
private void SelectorExample_Loaded(object sender, RoutedEventArgs e)
{
ListArrays = new ObservableCollection<UserModel>();
for (int i = 0; i < 200; i++)
{
ListArrays.Add(new UserModel { Name = i.ToString(), Date = DateTime.Now.AddDays(i) });
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var index = 150;
if (string.IsNullOrWhiteSpace(MyTextBox.Text) || !int.TryParse(MyTextBox.Text, out index))
index = 150;
SelectItem = ListArrays.FirstOrDefault(i => i.Name == index.ToString());
}
}
}
