이 리포지토리는 WPF Xaml Binding 개념과 기술을 활용하는데 필요한 설명을 다루는 Article입니다.
Star | License | Activity |
---|---|---|
DataContext는 FrameworkElement에 포함된 속성입니다.
PresentationFramework.dll
namespace System.Windows
{
public class FrameworkElement : UIElement
{
public static readonly DependencyProperty DataContextProperty;
public object DataContext { get; set; }
}
}
그리고 WPF의 모든 UI 컨트롤은 FrameworkElement
클래스를 상속합니다.
바인딩 또는 데이터 컨텍스트를 배워가는 시점에서 FrameworkElement를 더 깊이 연구할 필요가 없습니다. 하지만 모든 UI 컨트롤을 포함할 수 있는 가장 가까운 개체가 FrameworkElement라는 사실을 간단히 언급하기 위함입니다.
Binding can directly recall values for the DataContext type format starting with the nearest DataContext.
<TextBlock Text="{Binding}" DataContext="James"/>
Text="{Binding}
에 바인딩된 값은 가장 가까운 데이터 컨텍스트인 TextBlock
에서 직접 전달됩니다.
따라서 Text
의 바인딩 결과 값은 'James'입니다.
-
Type integer
Xaml에서 DataContext에 직접 값을 할당하는 경우 정수 및 부울과 같은 값 유형에 대해 먼저 리소스 정의가 필요합니다. 왜냐하면 모든 문자열이 문자열로 인식되기 때문입니다.Simple type variable type is not supported by standard.
어떤 단어로도 정의할 수 있지만 대부분sys
단어를 사용합니다.xmlns:sys="clr-namespace:System;assembly=mscorlib"
StaticResource 형식으로 생성할 유형의 값을 선언합니다.
<Window.Resources> <sys:Int32 x:Key="YEAR">2020</sys:Int32> </Window.Resources> ... <TextBlock Text="{Binding}" DataContext="{StaticResource YEAR"/>
-
All type of value
값이 데이터 컨텍스트에 직접 바인딩되는 경우는 거의 없습니다.
Because we're going to bind an object.<Window.Resources> <sys:Boolean x:Key="IsEnabled">true</sys:Boolean> <sys:double x:Key="Price">7.77</sys:double> </Window.Resources> ... <StackPanel> <TextBlock Text="{Binding}" DataContext="{StaticResource IsEnabled}"/> <TextBlock Text="{Binding}" DataContext="{StaticResource Price}"/> </StackPanel>
-
Another type
스트링뿐만 아니라 다양한 타입이 가능합니다. 데이터 컨텍스트가 객체이기 때문입니다.
WPF에서 바인딩을 사용할 때, 대부분의 개발자들은 DataContext의 기능 및 중요성에 대해 완전히 알지 못합니다. 특히 대규모 WPF 프로젝트를 담당하거나 참여하는 경우 애플리케이션의 DataContext 계층을 보다 명확하게 이해해야 합니다. DataContext 개념이 없으면 기능을 자유롭게 구현하는 데 한계가 있기 때문입니다.
- DataContext Binding
- Element Binding
- MultiBinding
- Self Property Binding
- Find Ancestor Binding
- TemplatedParent Binding
- Static Property Binding
string property
<TextBox Text="{Binding Keywords}"/>
<CheckBox x:Name="usingEmail"/>
<TextBlock Text="{Binding ElementName=usingEmail, Path=IsChecked}"/>
<TextBlock Margin="5,2" Text="This disappears as the control gets focus...">
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource TextInputToVisibilityConverter}">
<Binding ElementName="txtUserEntry2" Path="Text.IsEmpty" />
<Binding ElementName="txtUserEntry2" Path="IsFocused" />
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>
<TextBlock x:Name="txt" Text="{Binding ElementName=txt, Path=Tag}"/>
자신의 속성을 바인딩해야 하는 경우 요소 바인딩 대신 Element Binding
을 사용할 수 있습니다.
자신의 속성을 바인딩하기 위해 x:Name
을 선언할 필요가 없습니다.
<TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Path=Tag}"/>
가장 가까운 상위 컨트롤을 기준으로 가져옵니다.
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=Title}"/>
Trigger
에서 상위 개체의 속성에 액세스할 때 유용합니다.
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsSelected}" Value="True">
<Setter Property="Background" Value="#DDDDDD"/>
</DataTrigger>
DataContext 객체가 있는 경우 해당 속성을 사용할 수 있습니다.
그러나 DataContext
(ViewModel)에 대한 접근은 가급적 피하는 것이 좋습니다.
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.Email}"/>
현재 바인딩된 DataContext
가 아닌 다른 DataContext
를 바인딩하려는 경우 다음 방법을 사용할 수 있습니다.
public partial class A : UserControl
{
public A()
{
InitializeComponent();
DataContext = new MainViewModel();
}
public class MainViewModel
{
public B G1VM { get; set; } = new B();
public C G2VM { get; set; } = new C();
}
}
<TabControl DataContext="{Binding G1VM}">
<TabItem Header="TMP">
<DataGrid ItemsSource="{Binding datagrid}"
DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.G1VM}"/>
<!--It can also be expressed as follows.-->
<!--<DataGrid ItemsSource="{Binding datagrid}"
DataContext="{Binding Parent.G2VM}"/>-->
</TabItem>
</TabControl>
ControlTemplate
내에서 사용할 수 있는 메서드로 ControlTemplate
의 자신의 속성을 가져올 수 있습니다.
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
모든 속성 및 데이터 컨텍스트에 접근할 수 있습니다.
<TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"/>
바인딩 속성 값에 직접 접근할 수 있습니다.
namespace Exam
{
public class ExamClass
{
public static string ExamText { get; set; }
}
}
<Window ... xmlns:exam="clr-namespace:Exam">
<TextBlock Text="{Binding exam:ExamClass.ExamText}"/>
또는 Converter
를 사용하는 것처럼 리소스 키를 설정할 수 있습니다.
<Window.Resource>
<cvt:VisibilityToBooleanConverter x:Key="VisibilityToBooleanConverter"/>
<exam:ExamClass x:Key="ExamClass">
</Window.Resource>
...
<TextBlock Text="{Binding Source={StaticResource ExamClass}, Path=ExamText}"/>
DataContext에 포함된 속성에 해대해 ElementBinding을 사용하는 것은 기능적으로 문제가 없지만, 바인딩의 기본 패턴을 깰 수 있습니다.
<TextBox x:Name="text" Text="{Binding UserName}"/>
...
<TextBlock Text="{Binding ElementName=text, Path=Text}"/>
<TextBox Text="{Binding UserName}"/>
...
<TextBlock Text="{Binding UserName}"/>
<Window x:Name="win">
<TextBlock Text="{Binding ElementName=win, Path=DataContext.UserName}"/>
...
<Window>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.UserName}"/>
...
<Window>
<TextBlock DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext}"
Text="{Binding UserName}"/>
...
<TextBlock x:Name="txt" Text="{Binding ElementName=txt, Path=Foreground}"/>
<TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Path=Foreground}"/>
📑 StackOverflow How do I use WPF bindings with RelativeSource?