2013-09-30 53 views
3

我有一个ScrollViewer,它包含一个ItemsSource。这些项目绑定到ViewModel并按升序排序。允许用户将项目添加到此列表中,但是,由于排序顺序,列表需要滚动到底部。从我发现,ScrollViewer没有“锁定底部”功能,但有一个ScrollToEnd方法,这正是我要找的。将UI操作委托给ViewModel执行

但问题是,这些项目被添加到ViewModel中,并且ViewModel显然无法访问视图以调用ScrollViewer上的ScrollToEnd方法。为了解决这个问题,我宣布在视图模型的动作代表这样的:

public Action ScrollAction { get; set; } 

而且在创建视图模型的设置中查看:

viewModel.ScrollAction =() => scrollViewer.ScrollToEnd(); 

委托是在视图模型执行一次一个项目被添加到列表中。尽管这样做有效,但对我来说这有点不好意思,因为这种做法会破坏ViewModel与View的隔离。有没有更好的方法来实现这一目标?

+1

我喜欢它。可测试。足够分离。 – meilke

+1

您是否想过将附加行为添加到SV? –

+0

@GarryVass什么是SV? – PoweredByOrange

回答

1

我也会投票给您的滚动查看器的AttachedProperty。

我创建了以下附加属性来绑定滚动以布尔变量结束。

public static class ScrollViewerBehavior 
    { 
     public static readonly DependencyProperty ScrollToRightEndProperty = 
      DependencyProperty.RegisterAttached("ScrollToRightEnd", typeof (bool), typeof (ScrollViewerBehavior), 
               new PropertyMetadata(false, OnScrollToRightEndPropertyChanged)); 

     public static bool GetScrollToRightEnd(DependencyObject obj) 
     { 
      return (bool) obj.GetValue(ScrollToRightEndProperty); 
     } 

     public static void SetScrollToRightEnd(DependencyObject obj, bool value) 
     { 
      obj.SetValue(ScrollToRightEndProperty, value); 
     } 

     private static void OnScrollToRightEndPropertyChanged(DependencyObject sender, 
                   DependencyPropertyChangedEventArgs e) 
     { 
      var sv = sender as ScrollViewer; 
      if (sv == null) return; 

      if ((bool) e.NewValue) 
      { 
       sv.ScrollToRightEnd(); 
      } 
      else 
      { 
       sv.ScrollToLeftEnd(); 
      } 
     } 
    } 

你可以,如果你想在动作代表保存为你的问题使用您的XAML这个附加属性...

<ScrollViewer ... local:ScrollViewerBehavior.ScrollToRightEnd="{Binding IsScrolledToEnd}" ... /> 

或者,你可以做以下的OnScrollToRightEndPropertyChanged上述方法。

..... 
var viewModel = sv.DataContext as YourViewModel; 
if (viewModel != null) 
{ 
    viewModel.ScrollAction =() => sv.ScrollToRightEnd(); 
} 
..... 
+0

不错。 'AttachedProperty'的想法绝对比我原来的实现要好。 – PoweredByOrange