Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Okay, here's the answer I came up with for myself.</p> <p>I figured out that there is a GetSelfAndAncestors method for dependency objects. Using that, I am able to get the ScrollViewer ancestor(if there is one) of my AssociatedObject(the ItemsControl) and manipulate it with that.</p> <p>So I added this field to my behavior</p> <pre><code>private ScrollViewer scrollViewer; private bool isScrollDownEnabled; </code></pre> <p>And in the OnLoaded event handler I assigned it with the following code</p> <pre><code>scrollViewer = AssociatedObject.GetSelfAndAncestors().Where(a =&gt; a.GetType().Equals(typeof(ScrollViewer))).FirstOrDefault() as ScrollViewer; </code></pre> <p>And in the OnCollectionChanged event handler, I went ahead and wrapped all the logic in an if statement as follows</p> <pre><code> if (scrollViewer != null) { isScrollDownEnabled = scrollViewer.ScrollableHeight &gt; 0 &amp;&amp; scrollViewer.VerticalOffset + scrollViewer.ViewportHeight &lt; scrollViewer.ExtentHeight; if (e.Action == NotifyCollectionChangedAction.Add &amp;&amp; !isScrollDownEnabled) { // Do stuff } } </code></pre> <p>So all together, the code looks like the following</p> <pre><code>public class ScrollOnNewItem : Behavior&lt;ItemsControl&gt; { private ScrollViewer scrollViewer; private bool isScrollDownEnabled; protected override void OnAttached() { AssociatedObject.Loaded += OnLoaded; AssociatedObject.Unloaded += OnUnLoaded; } protected override void OnDetaching() { AssociatedObject.Loaded -= OnLoaded; AssociatedObject.Unloaded -= OnUnLoaded; } private void OnLoaded(object sender, RoutedEventArgs e) { var incc = AssociatedObject.ItemsSource as INotifyCollectionChanged; if (incc == null) return; incc.CollectionChanged += OnCollectionChanged; scrollViewer = AssociatedObject.GetSelfAndAncestors().Where(a =&gt; a.GetType().Equals(typeof(ScrollViewer))).FirstOrDefault() as ScrollViewer; } private void OnUnLoaded(object sender, RoutedEventArgs e) { var incc = AssociatedObject.ItemsSource as INotifyCollectionChanged; if (incc == null) return; incc.CollectionChanged -= OnCollectionChanged; } private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (scrollViewer != null) { isScrollDownEnabled = scrollViewer.ScrollableHeight &gt; 0 &amp;&amp; scrollViewer.VerticalOffset + scrollViewer.ViewportHeight &lt; scrollViewer.ExtentHeight; if (e.Action == NotifyCollectionChangedAction.Add &amp;&amp; !isScrollDownEnabled) { int count = AssociatedObject.Items.Count; if (count == 0) return; var item = AssociatedObject.Items[count - 1]; var frameworkElement = AssociatedObject.ItemContainerGenerator.ContainerFromItem(item) as FrameworkElement; if (frameworkElement == null) return; frameworkElement.BringIntoView(); } } } } </code></pre> <p>As asked in the comments, to use a behavior, I just need to add a new xmlns to my xaml file of the area in code that contains my behavior.</p> <pre><code> xmlns:behaviors="clr-namespace:Infrastructure.Behaviors;assembly=Infrastructure" </code></pre> <p>Then on the control I just add on the behavior.</p> <pre><code> &lt;ScrollViewer VerticalScrollBarVisibility="Auto"&gt; &lt;ItemsControl Name="Blah" ItemsSource="{Binding Messages}" ItemTemplate="{StaticResource MessageTemplate}"&gt; &lt;i:Interaction.Behaviors&gt; &lt;behaviors:ScrollOnNewItem /&gt; &lt;/i:Interaction.Behaviors&gt; &lt;/ItemsControl&gt; &lt;/ScrollViewer&gt; </code></pre> <p>The <strong>i</strong> class is just the interactivity namespace. <strong>xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"</strong></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload