UserControl에 Binding하기 위한 DependencyProperty 사용 방법
이전 포스트에서 Usercontrol에 Property를 추가하는 방법을 기술했는데,
WPF는 기본적으로 MVVM패턴을 사용하기 때문에 Xaml에서 사용한 컴포넌트를 ViewModel 쪽에서 Binding으로 묶어야하는 암묵적인 규약이 있습니다.
따라서 Usercontrol로 사용자가 임의로 지정해서 생성한 컴포넌트에 대해서도 Binding을 할 수 있어야 하는데 이때 DependencyProperty를 사용함으로 Binding을 할 수 있게 됩니다.
무슨 소리냐,
간략하게 얘기하자면 내가 자주 사용될 것 같은 TextBlock의 디자인을 Usercontrol을 사용해서 별도로 했는데,
이 TextBlock의 Text값이 항상 고정이면 안되고 동적으로 바뀌어야 하는 상황(항상 바뀌는 수치나 Name같은 것)에서 이러한 문제를 해결하기 위해 DependencyProperty를 사용합니다.
Binding이란 int value라는 0에서 10으로 변경되었다고 했을 때,
변경된 순간에 이 값을 Xaml쪽으로 알려서 Xaml의 값을 자동적으로 변경해주는 것인데,
자세한 Binding의 내용은 나중에 기술하겠습니다.
1. Usercontrol의 Xaml에서 속성을 정의해줍니다.
임의로 kW와 kVAR의 수치를 입력받아서 표현하는 Xaml을 구현했습니다.
<UserControl x:Class="EPCM.HMI.PSO.Component.KwTextComponent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:EPCM.HMI.PSO.Component"
mc:Ignorable="d" Foreground="{x:Null}" Background="#FFEDEDED" Width="50" Height="25" DataContext="{Binding}" x:Name="uc">
<Grid>
<TextBlock HorizontalAlignment="Left" Margin="5,0,0,0" TextWrapping="Wrap" Text="{Binding Path=kWValue, ElementName=uc}" VerticalAlignment="Top" Foreground="Black" FontSize="10"/>
<TextBlock HorizontalAlignment="Left" Margin="30,0,0,0" TextWrapping="Wrap" Text="kW" VerticalAlignment="Top" Foreground="Black" FontSize="10"/>
<TextBlock HorizontalAlignment="Left" Margin="5,10,0,0" TextWrapping="Wrap" Text="{Binding Path=kVARValue, ElementName=uc}" VerticalAlignment="Top" Foreground="Black" FontSize="10"/>
<TextBlock HorizontalAlignment="Left" Margin="30,10,0,0" TextWrapping="Wrap" Text="kVAR" VerticalAlignment="Top" Foreground="Black" FontSize="10"/>
</Grid>
</UserControl>
Text에 보면 Text="{Binding Path=kWValue, ElementName=uc}"라고 되어 있는 부분이 있는데 이 Path와 ElementName을 지정해서 cs쪽 코드의 특정 변수와 연결을 시켜줍니다.
Xaml쪽에서 해야할 것은 Usercontrol 쪽의 DataContext="{Binding}" x:Name="uc" 이 두 가지의 속성을 정의해주는 것과 사용하는 컴포넌트의 변경되는 값을 Binding Path, ElementName 속성을 정의하는 것입니다.
2. cs에서 DependencyProperty를 지정해줍니다.
namespace EPCM.HMI.PSO.Component
{
/// <summary>
/// TextComponent.xaml에 대한 상호 작용 논리
/// </summary>
public partial class KwTextComponent : UserControl
{
public KwTextComponent()
{
InitializeComponent();
}
public static readonly DependencyProperty kWValueProperty = DependencyProperty.Register(
"kWValue", typeof(string), typeof(KwTextComponent), new PropertyMetadata(string.Empty));
public string kWValue
{
get { return (string)GetValue(kWValueProperty); }
set { SetValue(kWValueProperty, value); }
}
public static readonly DependencyProperty kVARValueProperty = DependencyProperty.Register(
"kVARValue", typeof(string), typeof(KwTextComponent), new PropertyMetadata(string.Empty));
public string kVARValue
{
get { return (string)GetValue(kVARValueProperty); }
set { SetValue(kVARValueProperty, value); }
}
}
}
Xaml에서 Binding으로 연결한 변수 kWValue와 kVARValue를 get, set을 추가해줍니다.
그 다음에 DependencyProperty의 속성으로
DependencyProperty.Register("--Binding으로 연결하는 변수--",
typeof(--binding으로 연결된 변수의 타입--),
typeof(--usercontrol을 사용한 클래스의 이름--),
new PropertyMetadata(--기본은 null값으로--));
이 4가지를 지정해주면 Usercontrol에서 사용한 Text의 값을 Binding으로 엮여서 다른 곳에서 사용할 때도 Binding을 추가해줄 수 있습니다.
3. 사용하는 곳에서의 처리
- View 단
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:UC="clr-namespace:EPCM.HMI.PSO.Component"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
xmlns:vm="clr-namespace:EPCM.HMI.PSO.ViewModel"
x:Class="EPCM.HMI.PSO.View.VT2_NetworkDiagramView" x:Name="Owner"
mc:Ignorable="d" d:DesignHeight="600" d:DesignWidth="800"
DataContext="{DynamicResource VT2_NetworkDiagramViewModel}">
<UC:KwTextComponent kWValue="{Binding Path=ST1TR3kWValue, Mode=TwoWay}" kVARValue="{Binding Path=ST1TR3kVARValue, Mode=TwoWay}" Canvas.Top="31" Canvas.Left="136" Height="25" />
(기본적으로 Window에서 Usercontrol을 사용하지만 저는 Usercontrol에서 Usercontrol을 사용하는 코드를 예시로 사용했습니다.)
- ViewModel 단
public String sT1TR3kWValue;
public String ST1TR3kWValue
{
get { return sT1TR3kWValue; }
set { sT1TR3kWValue = value;
RaisePropertyChanged("ST1TR3kWValue");
}
}
KwTextComponent라는 Usercontrol을 지정해두었는데 이를 다른 곳에서 사용할 경우 kWValue값을 사용할 수 있게 되고 추가적으로 ViewModel에서 Binding을 사용할 수 있게 됩니다.
WPF에서는 빠지면 안될 기능이고 꼭 알아야 할 부분이죠.
'C# > WPF' 카테고리의 다른 글
WPF Fody 사용 방법 (0) | 2020.09.16 |
---|---|
[C#] nuget package manager console 사용 방법 (0) | 2020.09.03 |
[C#] Lazy Initialization(지연 초기화)란? (0) | 2020.09.01 |
[WPF] Text String Format Binding 사용 방법 (0) | 2020.08.31 |
[WPF] UserControl 에서 Property 속성 추가 방법 (2) | 2020.06.10 |