Xaml과 바인딩을 사용하여 ScrollViewer의 맨 아래까지 자동으로 스크롤하는 방법
나 있어TextBlock
이 컨텐츠는 ViewModel의 문자열 속성에 바인딩된 데이터입니다.이것.TextBlock
가 있다ScrollViewer
감쌌어요.
로그가 바뀔 때마다ScrollViewer
아래로 스크롤합니다.이상적으로는 다음과 같은 것을 원합니다.
<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollPosition="{Binding Path=ScrollPosition}">
<TextBlock Text="{Binding Path=Logs}"/>
</ScrollViewer>
코드 비하인드를 사용하고 싶지 않아!원하는 솔루션은 바인딩 및/또는 Xaml만 사용해야 합니다.
코드 배후에 사용하지 않고 원하는 것을 달성하기 위해 연결된 속성 또는 동작을 만들 수 있습니다.어느 쪽이든 코드를 작성해야 합니다.
다음은 첨부된 속성을 사용하는 예입니다.
부속 재산
public static class Helper
{
public static bool GetAutoScroll(DependencyObject obj)
{
return (bool)obj.GetValue(AutoScrollProperty);
}
public static void SetAutoScroll(DependencyObject obj, bool value)
{
obj.SetValue(AutoScrollProperty, value);
}
public static readonly DependencyProperty AutoScrollProperty =
DependencyProperty.RegisterAttached("AutoScroll", typeof(bool), typeof(Helper), new PropertyMetadata(false, AutoScrollPropertyChanged));
private static void AutoScrollPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var scrollViewer = d as ScrollViewer;
if (scrollViewer != null && (bool)e.NewValue)
{
scrollViewer.ScrollToBottom();
}
}
}
Xaml 바인딩
<ScrollViewer local:Helper.AutoScroll="{Binding IsLogsChangedPropertyInViewModel}" .../>
부울 속성을 생성해야 합니다.IsLogsChangedPropertyInViewModel
문자열 속성이 변경되면 true로 설정합니다.
이것이 도움이 되기를! :)
Answer updated 2017-12-13. 이제 ScrollChanged 이벤트를 사용하여 익스텐트의 크기가 변경되는지 확인합니다.신뢰성이 향상되어 수동 스크롤을 방해하지 않음
이 질문이 오래되었다는 것은 알지만, 구현이 개선되었습니다.
- 외부 의존관계 없음
- 속성을 한 번만 설정하면 됩니다.
이 코드는 Justin XL과 Contango의 솔루션에 크게 영향을 받습니다.
public static class AutoScrollBehavior
{
public static readonly DependencyProperty AutoScrollProperty =
DependencyProperty.RegisterAttached("AutoScroll", typeof(bool), typeof(AutoScrollBehavior), new PropertyMetadata(false, AutoScrollPropertyChanged));
public static void AutoScrollPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
var scrollViewer = obj as ScrollViewer;
if(scrollViewer != null && (bool)args.NewValue)
{
scrollViewer.ScrollChanged += ScrollViewer_ScrollChanged;
scrollViewer.ScrollToEnd();
}
else
{
scrollViewer.ScrollChanged-= ScrollViewer_ScrollChanged;
}
}
private static void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
// Only scroll to bottom when the extent changed. Otherwise you can't scroll up
if (e.ExtentHeightChange != 0)
{
var scrollViewer = sender as ScrollViewer;
scrollViewer?.ScrollToBottom();
}
}
public static bool GetAutoScroll(DependencyObject obj)
{
return (bool)obj.GetValue(AutoScrollProperty);
}
public static void SetAutoScroll(DependencyObject obj, bool value)
{
obj.SetValue(AutoScrollProperty, value);
}
}
사용방법:
<ScrollViewer n:AutoScrollBehavior.AutoScroll="True" > // Where n is the XML namespace
ScrollViewer AutoScroll 동작에 관한 Geoff 블로그에서 확인.
다음 클래스 추가:
namespace MyAttachedBehaviors
{
/// <summary>
/// Intent: Behavior which means a scrollviewer will always scroll down to the bottom.
/// </summary>
public class AutoScrollBehavior : Behavior<ScrollViewer>
{
private double _height = 0.0d;
private ScrollViewer _scrollViewer = null;
protected override void OnAttached()
{
base.OnAttached();
this._scrollViewer = base.AssociatedObject;
this._scrollViewer.LayoutUpdated += new EventHandler(_scrollViewer_LayoutUpdated);
}
private void _scrollViewer_LayoutUpdated(object sender, EventArgs e)
{
if (Math.Abs(this._scrollViewer.ExtentHeight - _height) > 1)
{
this._scrollViewer.ScrollToVerticalOffset(this._scrollViewer.ExtentHeight);
this._height = this._scrollViewer.ExtentHeight;
}
}
protected override void OnDetaching()
{
base.OnDetaching();
if (this._scrollViewer != null)
{
this._scrollViewer.LayoutUpdated -= new EventHandler(_scrollViewer_LayoutUpdated);
}
}
}
}
이 코드는 Blend Behaviors(혼합 동작)에 따라 달라집니다.이것에 대해서는, 다음의 참조가 필요합니다.System.Windows.Interactivity
. 추가 도움말을 참조하십시오.
MVVM Light NuGet 패키지를 설치하는 경우 여기에 참조를 추가할 수 있습니다.
packages\MvvmLightLibs.4.2.30.0\lib\net45\System.Windows.Interactivity.dll
헤더에 이 속성이 있는지 확인합니다.이 속성은 다음을 가리킵니다.System.Windows.Interactivity.dll
:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
에 블렌드 동작 추가ScrollViewer
:
<i:Interaction.Behaviors>
<implementation:AutoScrollBehavior />
</i:Interaction.Behaviors>
예:
<GroupBox Grid.Row="2" Header ="Log">
<ScrollViewer>
<i:Interaction.Behaviors>
<implementation:AutoScrollBehavior />
</i:Interaction.Behaviors>
<TextBlock Margin="10" Text="{Binding Path=LogText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" TextWrapping="Wrap"/>
</ScrollViewer>
</GroupBox>
네임스페이스에 대한 정의를 추가해야 합니다.그렇지 않으면 방금 추가한 C# 클래스를 찾을 수 없습니다.이 속성을 에 추가합니다.<Window>
태그. ReSharper를 사용하는 경우 자동으로 제안됩니다.
xmlns:implementation="clr-namespace:MyAttachedBehaviors"
모든 것이 잘 진행되면 상자의 텍스트가 항상 아래로 스크롤됩니다.
제공된 예 XAML은 바인딩된 속성의 내용을 인쇄합니다.LogText
로그 작성에 최적인 화면입니다.
간단합니다. 예를 들어 다음과 같습니다.
yourContronInside.ScrollOwner.ScrollToEnd ();
yourContronInside.ScrollOwner.ScrollToBottom ();
여기 약간의 변화가 있습니다.
스크롤 뷰어 높이(뷰포트)와 스크롤 발표자의 콘텐츠 높이(확장)가 변경되면 아래로 스크롤합니다.
Roy T의 답변에 근거하고 있습니다만, 코멘트를 할 수 없어서 답변으로 올렸습니다.
public static class AutoScrollHelper
{
public static readonly DependencyProperty AutoScrollProperty =
DependencyProperty.RegisterAttached("AutoScroll", typeof(bool), typeof(AutoScrollHelper), new PropertyMetadata(false, AutoScrollPropertyChanged));
public static void AutoScrollPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
var scrollViewer = obj as ScrollViewer;
if (scrollViewer == null) return;
if ((bool) args.NewValue)
{
scrollViewer.ScrollChanged += ScrollViewer_ScrollChanged;
scrollViewer.ScrollToEnd();
}
else
{
scrollViewer.ScrollChanged -= ScrollViewer_ScrollChanged;
}
}
static void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
// Remove "|| e.ViewportHeightChange < 0 || e.ExtentHeightChange < 0" if you want it to only scroll to the bottom when it increases in size
if (e.ViewportHeightChange > 0 || e.ExtentHeightChange > 0 || e.ViewportHeightChange < 0 || e.ExtentHeightChange < 0)
{
var scrollViewer = sender as ScrollViewer;
scrollViewer?.ScrollToEnd();
}
}
public static bool GetAutoScroll(DependencyObject obj)
{
return (bool) obj.GetValue(AutoScrollProperty);
}
public static void SetAutoScroll(DependencyObject obj, bool value)
{
obj.SetValue(AutoScrollProperty, value);
}
}
저는 @Roy T.의 답변을 사용하고 있었습니다만, 시간을 거슬러 스크롤하면 스크롤 뷰가 자동으로 아래로 스크롤된다는 조항을 추가하고 싶었습니다.
저는 이걸 썼어요
private static void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
var scrollViewer = sender as ScrollViewer;
if (e.ExtentHeightChange > 0)
{
scrollViewer.ScrollToEnd();
}
}
SizeChanged 이벤트 대신 사용됩니다.
언급URL : https://stackoverflow.com/questions/8370209/how-to-scroll-to-the-bottom-of-a-scrollviewer-automatically-with-xaml-and-bindin
'programing' 카테고리의 다른 글
Push git 커밋과 태그를 동시에 적용 (0) | 2023.04.15 |
---|---|
git commit을 삭제해도 변경은 유지할 수 있습니까? (0) | 2023.04.15 |
여러 커밋을 선택하는 방법 (0) | 2023.04.10 |
목록의 모든 문자열을 정수로 변환 (0) | 2023.04.10 |
WPF 탭 컨트롤에서 사다리꼴 탭을 만드는 방법 (0) | 2023.04.10 |