AttachedProperty.cs : 의존 속성
샘플 프로젝트에 AttachedProperty.cs 파일을 추가하고 SetFontPanel 클래스를 작성합니다.
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 | #region ChildrenFontSize public static readonly DependencyProperty ChildrenFontSizeProperty = DependencyProperty.RegisterAttached( "ChildrenFontSize", typeof(double), typeof(SetFontPanel), new PropertyMetadata((double)12, OnChildrenFontSizePropertyChanged)); public static double GetChildrenFontSize(DependencyObject dp) { return (double)dp.GetValue(ChildrenFontSizeProperty); } public static void SetChildrenFontSize(DependencyObject dp, double value) { dp.SetValue(ChildrenFontSizeProperty, value); } private static void OnChildrenFontSizePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var panel = sender as Panel; if (panel == null) return; SetFontProperties(panel); } #endregion | cs |
ChildrenFontSize라는 Attached Property를 작성했습니다. Attached property도 Dependency property입니다. Dependency property는 Register 함수로 정의하고 Attached property는 RegisterAttached 함수로 정의하는 차이가 있습니다. Get과 Set 함수를 갖고 있는 점도 특징입니다. 더 자세한 내용은 박문찬 MVP님의 블로그를 참고하세요.
추가로 PropertyChanged 이벤트가 발생할 때마다 SetFontProperties 함수가 호출되도록 했습니다.
#region ChildrenForeground
.....
#endregion
ChildrenForeground라는 결합 속성도 추가했지만 반복되는 내용이므로 설명은 생략합니다.
FontFamily, FontWeight, FontStyle, FontStretch 등 사용하고자하는 결합 속성들이 추가될 수 있습니다.
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 | #region Attach public static readonly DependencyProperty AttachProperty = DependencyProperty.RegisterAttached( "Attach", typeof(bool), typeof(SetFontPanel), new PropertyMetadata(false, OnAttachPropertyChanged)); public static bool GetAttach(DependencyObject dp) { return (bool)dp.GetValue(AttachProperty); } public static void SetAttach(DependencyObject dp, bool value) { dp.SetValue(AttachProperty, value); } private static void OnAttachPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var panel = sender as Panel; if (panel == null) return; if ((bool)e.NewValue) { panel.Loaded += panel_Loaded; } else { panel.Loaded -= panel_Loaded; } } #endregion | cs |
Loaded 이벤트일 때 한번만 SetFontProperties 함수를 호출하기 위해서 Attach라는 bool형의 결합 속성도 추가했습니다.
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 | #region Method private static void SetFontProperties(Panel panel) { foreach (var child in panel.Children) { if (child == null) return; if (child is TextBlock) { var txt = child as TextBlock; if (txt == null) return; txt.FontSize = GetChildrenFontSize(panel); txt.Foreground = GetChildrenForeground(panel); // FontFamily // FontWeight // FontStyle // FontStretch } else if (child is Control) { var ctr = child as Control; if (ctr == null) return; ctr.FontSize = GetChildrenFontSize(panel); ctr.Foreground = GetChildrenForeground(panel); // FontFamily // FontWeight // FontStyle // FontStretch } //else if (또 다른 컨트롤을 추가) //{ //} } } #endregion | cs |
Panel 안에 들어간 컨트롤들을 모두 찾아 앞에서 추가한 결합 속성들을 알맞은 속성에 대입해주는 함수를 작성했습니다. 파라미터를 Panel로 지정해 WrapPanel, UniformGrid 등 Panel을 상속 받은 레이아웃 패널이라면 범용적으로 사용 가능하도록 했습니다.
1 | xmlns:atcp="clr-namespace:Sample.AttachedProperty" | cs |
앞에서 작성한 결합 속성을 XAML에서 사용하기 위해 네임스페이스를 선언합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <!-- Attached property --> <StackPanel x:Name="spParent" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" atcp:SetFontPanel.ChildrenFontSize="15" atcp:SetFontPanel.ChildrenForeground="Red" atcp:SetFontPanel.Attach="True"> <!-- [Prefix].[ClassName].[AttachedProperty] --> <Label Content="Attached property"/> <TextBlock Text="Lorem Ipsum is simply "/> <TextBlock Text="dummy text of the"/> <TextBlock Text="printing and typesetting "/> <TextBlock Text="industry."/> </StackPanel> | cs |
결합 속성을 사용하는 방법은 위와 같습니다. "[접두사].[클래스명].[결합속성명]"
부모가 자식들을 일괄적으로 Font 관련 속성들을 정의할 수 있게 되었습니다. 결합 속성이 일반 속성과 다른 점은 직접 사용하는 속성이 아니라 다른 요소가 사용하도록 하는 점입니다. 이 예제에서는 자식들이 그 결합 속성을 사용하도록 했습니다.
1 2 3 4 5 6 7 8 9 10 11 12 | <Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <TextBlock Grid.Column="1"/> </Grid> <Canvas> <TextBlock Canvas.Left="100" Canvas.Top="50"/> </Canvas> | cs |
부모 Grid의 자식인 TextBlock에 선언된 Grid.Column 속성과 부모 Canvas의 자식인 TextBlock에 선언된 Canvas.Left 속성이 바로 결합속성입니다. 자신에게 없는 속성이지만 각 패널 안에서 위치를 정의하는데 사용되고 있습니다.
이처럼 결합속성은 자신이 가지고 있지 않은 속성을 정의해 다양한 방식으로 응용될 수 있습니다. 위 예제에서는 부모가 자식의 위치를 직접 정의해줄 수 없기 떄문에 자식 스스로가 부모의 결합속성을 이용해 자신의 위치를 정의하고 있는 것입니다.
샘플 코드 : https://github.com/CharlesKwon/XamlSimplified
'XAML 뽀개기' 카테고리의 다른 글
016. 두개의 콘텐츠 버튼(Two Contents Button) #2 (0) | 2018.02.02 |
---|---|
015. 두개의 콘텐츠 버튼(Two Contents Button) #1 (0) | 2018.01.31 |
014. 결합 속성(Attached property) (0) | 2018.01.28 |
013. 속성 상속(Resolved Dynamically) (0) | 2018.01.24 |
012. 컨버터(Value Converter) (0) | 2018.01.22 |
011. 의존 속성(Dependency Property) (0) | 2018.01.19 |