如何滚动到添加到 MVVM Light 列表视图中的新项目
Posted
技术标签:
【中文标题】如何滚动到添加到 MVVM Light 列表视图中的新项目【英文标题】:How to Scroll to a new item added to a list view in MVVM Light 【发布时间】:2015-01-20 21:06:49 【问题描述】:我有一个项目,其中有一个 ListView,当用户单击“新建”按钮时,新对象将添加到 ListView 的底部。我尝试过使用 Content Style 类,但没有奏效。我只需要一些可以滚动到所选项目的东西。以下是我的代码:
查看:
<ListView Margin="103,0,0,10" ScrollViewer.CanContentScroll="True" Height="87" SelectedItem="Binding SelectedSession, Mode=TwoWay" ItemsSource="Binding SessionCollection">
<ListView.Resources>
<Style TargetType="x:Type GridViewColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Left" />
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="Session Name" Width="180" DisplayMemberBinding="Binding SessionName, Mode=TwoWay" />
<GridViewColumn Header="Operator Name" Width="180" DisplayMemberBinding="Binding OperatorName, Mode=TwoWay"/>
<GridViewColumn Header="Session Date" Width="180" DisplayMemberBinding="Binding SessionDate, Mode=TwoWay"/>
</GridView>
</ListView.View>
</ListView>
查看新按钮的模型代码:
public void NewSession()
Session newSession = new Session();
SessionCollection.Add(newSession);
SelectedSession = newSession;
SessionDate = DateTime.Now;
StartTime = DateTime.Now;
EndTime = DateTime.Now;
ProjectManager.Instance.CurrentSession = null;
public ObservableCollection<Session> SessionCollection
get
if (currentDatabaseProj.Sessions == null)
return currentDatabaseProj.Sessions;
else
return currentDatabaseProj.Sessions;
private set
currentDatabaseProj.Sessions = value;
IsNewProjClicked = true;
this.RaisePropertyChanged("SessionCollection");
【问题讨论】:
如果我猜对了,当单击“新按钮”时,您正在将所选项目设置为新元素? 是的。完全正确。 设置SelectedItem
不会自动聚焦它。请参阅this 主题以获取更多信息,如何设置它。
Herdo 并不真正适用于 MVVM。
【参考方案1】:
后面代码中的一个简单处理程序应该可以解决问题 (我简化了您的代码以使其清晰)
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView x:Name="listView" Margin="10" ScrollViewer.CanContentScroll="True" SelectedItem="Binding SelectedSession, Mode=TwoWay" ItemsSource="Binding SessionCollection">
<ListView.Resources>
<Style TargetType="x:Type GridViewColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Left" />
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="Session Name" Width="180" DisplayMemberBinding="Binding" />
</GridView>
</ListView.View>
</ListView>
<Button Click="UIElement_NewElementHandler" Grid.Row="1" Content="Add Item" Command="Binding AddItem"></Button>
</Grid>
并在视图代码后面添加以下处理程序:
private void UIElement_NewElementHandler(object sender, RoutedEventArgs routedEventArgs)
var border = VisualTreeHelper.GetChild(listView, 0) as Decorator;
var scrollViewer = border.Child as ScrollViewer;
scrollViewer.ScrollToBottom();
ps:向下滚动到新添加的项目是与视图相关的,代码隐藏中没有使用任何视图模型属性,所以我相信你这样做并没有违反任何 mvvm 规则。
【讨论】:
【参考方案2】:行为示例
xaml
<Window x:Class="ListView.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:listView="clr-namespace:ListView"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Content="Add New" Grid.Row="0" Click="Button_Click"></Button>
<ListView Grid.Row="1" ItemsSource="Binding MySessionList" SelectedItem="Binding SelectedSession, Mode=TwoWay">
<i:Interaction.Behaviors>
<listView:ScrollIntoViewBehavior/>
</i:Interaction.Behaviors>
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="200" DisplayMemberBinding="Binding Name, Mode=TwoWay" />
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
cs
public partial class MainWindow : Window
private Viewmodel _data;
public MainWindow()
InitializeComponent();
_data = new Viewmodel();
this.DataContext = _data;
private void Button_Click(object sender, RoutedEventArgs e)
_data.AddNew();
public class Viewmodel : INotifyPropertyChanged
private MySession _selectedSession;
public ObservableCollection<MySession> MySessionList get; set;
public Viewmodel()
this.MySessionList = new ObservableCollection<MySession>();
//fill with some data
for (int i = 0; i < 20; i++)
this.MySessionList.Add(new MySession()Name = "Index : " + i);
public MySession SelectedSession
get return _selectedSession;
set
_selectedSession = value;
OnPropertyChanged();
//should be a Command for MVVM but for quick and dirty
public void AddNew()
var toAdd = new MySession() Name = "New Added " + DateTime.Now.ToLongTimeString();
this.MySessionList.Add(toAdd);
this.SelectedSession = toAdd;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
public class MySession
public string Name get; set;
//ADD REFERENCE: System.Windows.Interactivity
public class ScrollIntoViewBehavior : Behavior<ListBox>
protected override void OnAttached()
base.OnAttached();
AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
private void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
var ctrl = sender as ListBox;
if (ctrl == null)
return;
if (ctrl.SelectedItem != null)
ctrl.Dispatcher.BeginInvoke(
DispatcherPriority.Render,
new Action(() =>
ctrl.UpdateLayout();
ctrl.ScrollIntoView(ctrl.SelectedItem);
));
protected override void OnDetaching()
base.OnDetaching();
AssociatedObject.SelectionChanged -= AssociatedObject_SelectionChanged;
【讨论】:
有一个问题,我的新会话代码会在单击按钮的地方引发问题吗?我在哪里创建一个新的会话对象并设置 SelectedSession = newSession;? 我在哪里可以得到行为添加我在我的以上是关于如何滚动到添加到 MVVM Light 列表视图中的新项目的主要内容,如果未能解决你的问题,请参考以下文章
如何过滤列表视图中的内部子元素以及使用 Jquery 在移动应用程序中将字母滚动条添加到列表视图的任何简单方法
带有 MVVM Light 的标签栏控制器导航 Xamarin