2013-09-30 2 views
3

У меня есть ScrollViewer, который содержит ItemsSource. Элементы привязаны к ViewModel и сортируются в порядке возрастания. Пользователям разрешено добавлять элементы в этот список, однако список необходимо прокручивать снизу из-за порядка сортировки. Из того, что я нашел, ScrollViewer не имеет функции «блокировки до дна», но имеет метод ScrollToEnd, который выполняет то, что я ищу.Делегирование действий пользовательского интерфейса на ViewModel для выполнения

Проблема заключается в том, что элементы добавлены в ViewModel, и ViewModel, очевидно, не имеет доступа к представлению для вызова метода ScrollToEnd на ScrollViewer. Чтобы обойти эту проблему, я заявил делегат действий в ViewModel, как это:

public Action ScrollAction { get; set; } 

и установить его в представлении при создании ViewModel:

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

Делегат выполняется в ViewModel раз элемент добавляется в список. Несмотря на то, что это работает, это кажется мне немного взломанным, поскольку этот вид прерывает изоляцию ViewModel от представления. Есть ли лучший способ достичь этого?

+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

Смежные вопросы