■ ScrollViewer 클래스에서 시프트 키와 마우스 휠을 사용해 가로 스크롤을 처리하는 방법을 보여준다.
▶ ScrollViewerHelper.cs
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; namespace TestProject { /// <summary> /// 스크롤 뷰어 헬퍼 /// </summary> public static class ScrollViewerHelper { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 시프트/휠 사용 여부 속성 /// </summary> public static readonly DependencyProperty UseShiftWheelProperty = DependencyProperty.RegisterAttached ( "UseShiftWheel", typeof(bool), typeof(ScrollViewerHelper), new PropertyMetadata(false, UseShiftWheelPropertyChangedCallback) ); #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region 시프트/휠 사용 여부 설정하기 - SetUseShiftWheel(uiElement, value) /// <summary> /// 시프트/휠 사용 여부 설정하기 /// </summary> /// <param name="uiElement">UI 엘리먼트</param> /// <param name="value">값</param> public static void SetUseShiftWheel(UIElement uiElement, bool value) => uiElement.SetValue(UseShiftWheelProperty, value); #endregion #region 시프트/휠 사용 여부 구하기 - GetUseShiftWheel(uiElement) /// <summary> /// 시프트/휠 사용 여부 구하기 /// </summary> /// <param name="uiElement">UI 엘리먼트</param> /// <returns>시프트/휠 사용 여부</returns> public static bool GetUseShiftWheel(UIElement uiElement) => (bool)uiElement.GetValue(UseShiftWheelProperty); #endregion //////////////////////////////////////////////////////////////////////////////// Private ////////////////////////////////////////////////////////////////////// Event #region UI 엘리먼트 마우스 휠 PREVIEW 처리하기 - uiElement_PreviewMouseWheel(sender, e) /// <summary> /// UI 엘리먼트 마우스 휠 PREVIEW 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private static void uiElement_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { ScrollViewer scrollViewer = ((UIElement)sender).FindDescendant<ScrollViewer>(); if(scrollViewer == null) { return; } if(Keyboard.Modifiers != ModifierKeys.Shift) { return; } if(e.Delta < 0) { scrollViewer.LineRight(); } else { scrollViewer.LineLeft(); } e.Handled = true; } #endregion ////////////////////////////////////////////////////////////////////// Function #region 시프트/휠 사용 여부 속성 변경시 콜백 처리하기 - UseShiftWheelPropertyChangedCallback(dependencyObject, e) /// <summary> /// 시프트/휠 사용 여부 속성 변경시 콜백 처리하기 /// </summary> /// <param name="dependencyObject">의존 객체</param> /// <param name="e">이벤트 인자</param> private static void UseShiftWheelPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { UIElement uiElement = dependencyObject as UIElement; if(uiElement == null) { throw new Exception("Attached property must be used with UIElement."); } if((bool)e.NewValue) { uiElement.PreviewMouseWheel += uiElement_PreviewMouseWheel; } else { uiElement.PreviewMouseWheel -= uiElement_PreviewMouseWheel; } } #endregion #region 자손 찾기 - FindDescendant<T>(dependencyObject) /// <summary> /// 자손 찾기 /// </summary> /// <typeparam name="T">자손 타입</typeparam> /// <param name="dependencyObject">의존 객체</param> /// <returns>자손</returns> private static T FindDescendant<T>(this DependencyObject dependencyObject) where T : DependencyObject { if(dependencyObject == null) { return null; } int count = VisualTreeHelper.GetChildrenCount(dependencyObject); for(var i = 0; i < count; i++) { DependencyObject child = VisualTreeHelper.GetChild(dependencyObject, i); T result = child as T ?? FindDescendant<T>(child); if(result != null) { return result; } } return null; } #endregion } } |
▶ MainWindow.xaml
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 40 |
<Window x:Class="TestProject.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:src="clr-namespace:TestProject" Width="800" Height="600" Title="ScrollViewer 클래스 : 시프트 키와 마우스 휠을 사용해 가로 스크롤 처리하기" FontFamily="나눔고딕코딩" FontSize="16"> <Grid src:ScrollViewerHelper.UseShiftWheel="True"> <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> <StackPanel Orientation="Horizontal"> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> <Rectangle Width="50" Height="50" Margin="10" Fill="Blue" /> </StackPanel> </ScrollViewer> </Grid> </Window> |