关于c#:WPF覆盖列表框中的ScrollVIewer

WPF overriding ScrollVIewer in Listbox

我制作了一个名为" AniScrollViewer"的类,它可以设置垂直滚动偏移量
动画化Scrollviewer背后的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class AniScrollViewer : ScrollViewer {
    public static readonly DependencyProperty CurrentVerticalOffsetProperty =
        DependencyProperty.Register("CurrentVerticalOffset", typeof(double), typeof(AniScrollViewer),
        new PropertyMetadata(new PropertyChangedCallback(OnVerticalChanged)));

    public double CurrentVerticalOffset {
        get { return (double)GetValue(CurrentVerticalOffsetProperty); }
        set { SetValue(CurrentVerticalOffsetProperty, value); }
    }

    private static void OnVerticalChanged(DependencyObject property, DependencyPropertyChangedEventArgs e) {
        AniScrollViewer viewer = property as AniScrollViewer;
        viewer.ScrollToVerticalOffset((double)e.NewValue);
    }
}

我想将此" AniScrollViewer"推送到列表框中

我遇到几个问题:

  • Listbox类中已经包含" scrollviewer"。我要更换
    默认的列表框带有我的自定义AniScrollViewer的scrollviewer,但是我不知道该怎么做。
  • 我想在列表框代码的后面获取ScrollViewer。像这样:

列表框列表框(已在XAML中定义)
AniScrollViewer scrollviewer =列表框。~~~~;

请帮助。


  • 要将默认的ScrollViewer替换为自定义的ScrollViewer,请为ListBox定义一个自定义的Style,然后在ControlTemplate中,将默认的ScrollViewer替换为您的一个(local:AniScrollViewer)。现在,任何使用此StyleListBox都将具有您的ScrollViewer。默认ControlTemplateStyle可以在此处找到
  • 要在后面的代码中获取ScrollViewer,您可以将其用作参考。在功能上

GetScrollViewer(DependencyObject o)

使用您的自定义ScrollViewer(例如,

)检查其是否安全

1
2
if (o is AniScrollViewer)
  return o;

替代

但是,对于您来说,不确定为什么选择为此ScrollViewer子类化。代替定义自己的ListBox ControlTemplate的麻烦,也许尝试使用附加属性。类似于:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class ScrollAnimator {
  public static readonly DependencyProperty ScrollToProperty =
    DependencyProperty.RegisterAttached(
     "ScrollTo",
      typeof(double),
      typeof(ScrollAnimator),
      new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.None, ScrollToChangedCallback));

  private static void ScrollToChangedCallback(
    DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) {
    ScrollViewer viewer = GetScrollViewer(dependencyObject) as ScrollViewer;
    if (viewer != null)
      viewer.ScrollToVerticalOffset((double)dependencyPropertyChangedEventArgs.NewValue);

    // Modify Above code to however you want to do the animation.
  }

  public static DependencyObject GetScrollViewer(DependencyObject o) {
    if (o is ScrollViewer)
      return o;

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++) {
      var child = VisualTreeHelper.GetChild(o, i);
      var result = GetScrollViewer(child);
      if (result == null)
        continue;
      return result;
    }
    return null;
  }

  public static void SetScrollTo(UIElement element, Orientation value) {
    element.SetValue(ScrollToProperty, value);
  }

  public static Orientation GetScrollTo(UIElement element) {
    return (Orientation)element.GetValue(ScrollToProperty);
  }
}

和用法:

1
2
<ListBox ItemsSource="{Binding Items}"
         local:ScrollAnimator.ScrollTo="{Binding ScrollTo}" />

这样,您无需定义自定义ControlTemplate及其自带的所有开销。