Skip to content

jamesnet214/wpf-xaml-binding

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Xaml Binding

์ด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋Š” WPF Xaml Binding ๊ฐœ๋…๊ณผ ๊ธฐ์ˆ ์„ ํ™œ์šฉํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์„ค๋ช…์„ ๋‹ค๋ฃจ๋Š” Article์ž…๋‹ˆ๋‹ค.

๋” ์•Œ์•„๋ณด๊ธฐ ยป

Star License Activity
Github Stars License Commits-per-month

DataContext

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๋ผ๋Š” ์‚ฌ์‹ค์„ ๊ฐ„๋‹จํžˆ ์–ธ๊ธ‰ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค.


DataContext is always the reference point for Binding.

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์— ์ง์ ‘ ๊ฐ’์„ ํ• ๋‹นํ•˜๋Š” ๊ฒฝ์šฐ ์ •์ˆ˜ ๋ฐ ๋ถ€์šธ๊ณผ ๊ฐ™์€ ๊ฐ’ ์œ ํ˜•์— ๋Œ€ํ•ด ๋จผ์ € ๋ฆฌ์†Œ์Šค ์ •์˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๋ชจ๋“  ๋ฌธ์ž์—ด์ด ๋ฌธ์ž์—ด๋กœ ์ธ์‹๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

    1. Xaml์—์„œ System mscrollib ์‚ฌ์šฉ

    Simple type variable type is not supported by standard.
    ์–ด๋–ค ๋‹จ์–ด๋กœ๋„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋Œ€๋ถ€๋ถ„ sys ๋‹จ์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    xmlns:sys="clr-namespace:System;assembly=mscorlib"

    2. xaml์—์„œ YEAR ๋ฆฌ์†Œ์Šค ํ‚ค ์ƒ์„ฑ

    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 ๊ฐœ๋…์ด ์—†์œผ๋ฉด ๊ธฐ๋Šฅ์„ ์ž์œ ๋กญ๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ํ•œ๊ณ„๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.



Binding


DataContext Binding

string property

<TextBox Text="{Binding Keywords}"/>

Element Binding

<CheckBox x:Name="usingEmail"/>
<TextBlock Text="{Binding ElementName=usingEmail, Path=IsChecked}"/>

MultiBinding

<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>

Self Property Binding

<TextBlock x:Name="txt" Text="{Binding ElementName=txt, Path=Tag}"/>

์ž์‹ ์˜ ์†์„ฑ์„ ๋ฐ”์ธ๋”ฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์š”์†Œ ๋ฐ”์ธ๋”ฉ ๋Œ€์‹  Element Binding์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ž์‹ ์˜ ์†์„ฑ์„ ๋ฐ”์ธ๋”ฉํ•˜๊ธฐ ์œ„ํ•ด x:Name์„ ์„ ์–ธํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

<TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Path=Tag}"/>

Find Ancestor Binding

๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ƒ์œ„ ์ปจํŠธ๋กค์„ ๊ธฐ์ค€์œผ๋กœ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

<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>

TemplatedParent Binding

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}"/>

Static Property Binding

๋ฐ”์ธ๋”ฉ ์†์„ฑ ๊ฐ’์— ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1. static ์†์„ฑ์„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

namespace Exam
{
  public class ExamClass
  {
      public static string ExamText { get; set; }
  }
} 

2. XAML์—์„œ ์ •์  ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

<Window ... xmlns:exam="clr-namespace:Exam">

3. Binding property.

<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}"/>


Bad Binding & Good Binding

โœ”๏ธ ๋ฐ”์ธ๋”ฉํ•  ์†์„ฑ์ด DataContext์— ํฌํ•จ๋œ ๊ฒฝ์šฐ ElementBinding์„ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

DataContext์— ํฌํ•จ๋œ ์†์„ฑ์— ํ•ด๋Œ€ํ•ด ElementBinding์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๊ธฐ๋Šฅ์ ์œผ๋กœ ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ, ๋ฐ”์ธ๋”ฉ์˜ ๊ธฐ๋ณธ ํŒจํ„ด์„ ๊นฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ™ Bad Binding

<TextBox x:Name="text" Text="{Binding UserName}"/>
...
<TextBlock Text="{Binding ElementName=text, Path=Text}"/>

๐Ÿ˜€ Good Binding

<TextBox Text="{Binding UserName}"/>
...
<TextBlock Text="{Binding UserName}"/>

โœ”๏ธ ์ƒ์œ„ ์ปจํŠธ๋กค์˜ ์†์„ฑ์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ElementBinding์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”.

๐Ÿ™ Bad Binding

<Window x:Name="win">
  <TextBlock Text="{Binding ElementName=win, Path=DataContext.UserName}"/>
  ...

๐Ÿ˜€ Good Binding

<Window>
  <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.UserName}"/>
  ...

๐Ÿ˜† Great!

<Window>
  <TextBlock DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext}" 
             Text="{Binding UserName}"/>
  ...

โœ”๏ธ ์ž๊ธฐ ์ž์‹ ์˜ ์†์„ฑ์„ ์‚ฌ์šฉํ•  ๋•Œ ElementBinding์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”.

๐Ÿ™ Bad Binding

<TextBlock x:Name="txt" Text="{Binding ElementName=txt, Path=Foreground}"/>

๐Ÿ˜€ Good Binding

<TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Path=Foreground}"/>

Reference

๐Ÿ“‘ StackOverflow ย  How do I use WPF bindings with RelativeSource?

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •