开发者

Outlook-style Spacebar reading with WPF and MVVM

One great feature of Microsoft Outlook is its spacebar reading mode (with the reading pane turned on). Say there are 5 messages in your inbo开发者_StackOverflow中文版x and the first one is displayed. The displayed message does not entirely fit on the screen, so when you press the spacebar, that is like pagedown within the message. You hit spacebar again, and it pages down again. When you've reached the bottom of the page, and you press spacebar again, it goes to the next message.

What is a good way to do this in WPF (where the application is built using the MVVM pattern)? With MVVM, I use a bunch of DataTemplates instead of usercontrols.

Edit: I should mention that I am using a ListBox for the messages and a FlowDocumentScrollViewer for the message body.


Use Expression Blend's KeyTrigger to invoke the Command in your view model

http://msdn.microsoft.com/en-us/library/microsoft.expression.interactivity.input.keytrigger%28v=expression.40%29.aspx

OR

Use CommandReference from MVVM Toolkit How do I associate a keypress with a DelegateCommand in Composite WPF?


For posterity, here's my solution to the scrolling part of the question. This code handles the space first, then, if the scroll bar is already at the bottom, it doesn't handle the KeyDown. @Hasan's recomended commend fires at that point.

internal class FlowDocumentScrollViewer2 : FlowDocumentScrollViewer
{
  private static bool PageDown<T>(T listView)
     where T : DependencyObject
  {
     var scrollViewer = GetVisualChild<ScrollViewer>(listView, null);
     var scrollBar = GetVisualChild<ScrollBar>(listView,
                                               bar => bar.Orientation == Orientation.Vertical);
     var formerOffset = scrollBar.Track.Value;
     scrollViewer.PageDown();
     scrollBar.Track.UpdateLayout();
     return formerOffset < scrollBar.Track.Value;
  }

  private static T GetVisualChild<T>(DependencyObject parent, Predicate<T> predicate)
     where T : Visual
  {
     T child = default(T);
     int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
     for (int i = 0; i < numVisuals; i++)
     {
        Visual v = (Visual) VisualTreeHelper.GetChild(parent, i);
        child = v as T;
        if (child == null)
        {
           child = GetVisualChild(v, predicate);
        }
        if (child != null && (predicate == null || predicate(child)))
        {
           break;
        }
     }
     return child;
  }

  public FlowDocumentScrollViewer2()
  {
     PreviewKeyDown += PreviewSpaceDown;
  }

  private void PreviewSpaceDown(object sender, KeyEventArgs e)
  {
     if (e.Handled)
        return;
     if (e.Key == Key.Space)
     {
        e.Handled = PageDown(this);
     }
  }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜