코드 숨김에 정의 된 바인딩 개체


88

예를 들어 XAML은 window.xaml이라고하며 window.xaml.cs 내에있는 코드에서 인스턴스화되는 개체가 있습니다.

protected Dictionary<string, myClass> myDictionary;

XAML 태그 만 사용하여이 개체를 예를 들어 목록보기에 바인딩하려면 어떻게해야합니까?

최신 정보:

(이것은 정확히 내 테스트 코드에 있습니다) :

<Window x:Class="QuizBee.Host.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="{Binding windowname}" Height="300" Width="300"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
    </Grid>
</Window>

그리고 코드 숨김에서

public partial class Window1 : Window
{
    public const string windowname = "ABCDEFG";

    public Window1()
    {
        InitializeComponent();
    }
}

제목이 "ABCDEFG"가되어야한다고 가정하겠습니다. 맞습니까? 하지만 아무것도 보여주지 않습니다.


1
이상하게도 창의 속성 할당 순서를 변경하면 작동하지 않습니다. "Title"Property 다음에 "DataContext"Property를 설정하면 바인딩이 발생하지 않습니다. 누구든지 이것을 설명 할 수 있습니까? <Window x : Class = "INotifyPropertyTest.MainWindow"xmlns = " schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns : x = " schemas.microsoft.com/winfx/2006/xaml"xmlns : local = " clr-namespace : INotifyPropertyTest "Height ="350 "Width ="525 "DataContext ="{Binding RelativeSource = {RelativeSource self}} "Title ="{Binding WindowName} ">
Ramesh

답변:


109

다음과 같이 컨트롤, 양식 등에 대한 DataContext를 설정할 수 있습니다.

DataContext="{Binding RelativeSource={RelativeSource Self}}"

설명 :

위의 값으로 설정되는 데이터 컨텍스트는 뒤에있는 코드를 "소유하는"요소에서 수행되어야합니다. 따라서 Window의 경우 Window 선언에서 설정해야합니다.

이 코드로 작업하는 예제가 있습니다.

<Window x:Class="MyClass"
  Title="{Binding windowname}"
  DataContext="{Binding RelativeSource={RelativeSource Self}}"
  Height="470" Width="626">

이 수준에서 설정된 DataContext는 창에있는 모든 요소에 상속되므로 (하위 요소에 대해 명시 적으로 변경하지 않는 한) Window에 대한 DataContext를 설정 한 후에 는 모든 컨트롤에서 CodeBehind 속성에 직접 바인딩 할 수 있어야합니다. 창문에.


1
여기서 "Self"는 전체 창 클래스가 아니라 컨트롤을 의미합니다.
xandy

이상하게도 다음은 내가 가지고있는 코드이며 예상대로 작동하지 않습니다. public partial class Window1 : Window {public const string windowname = "ABCDEFG"; public Window1 () {InitializeComponent (); }} <Window x : Class = "QuizBee.Host.Window1"xmlns = " schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns : x = " schemas.microsoft.com/winfx/2006/xaml "제목 = "{Binding windowname}"Height = "300"Width = "300"DataContext = "{Binding RelativeSource = {RelativeSource Self}}"> </ Window>
xandy

9
아, 이제 괜찮습니다. windowname을 순수한 공용 변수 대신 속성으로 변경했으며 이제 표시 할 수 있습니다! 감사!
xandy

1
왜 이것이 기본적으로 설정되지 않았는지 상상할 수 없습니다.
Okonomiyaki3000

122

이 작업을 수행하는 훨씬 쉬운 방법이 있습니다. Window 또는 UserControl에 Name을 할당 한 다음 ElementName으로 바인딩 할 수 있습니다.

Window1.xaml

<Window x:Class="QuizBee.Host.Window1"
        x:Name="Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ListView ItemsSource="{Binding ElementName=Window1, Path=myDictionary}" />
</Window>

Window1.xaml.cs

public partial class Window1:Window
{
    // the property must be public, and it must have a getter & setter
    public Dictionary<string, myClass> myDictionary { get; set; }

    public Window1()
    {
        // define the dictionary items in the constructor
        // do the defining BEFORE the InitializeComponent();

        myDictionary = new Dictionary<string, myClass>()
        {
            {"item 1", new myClass(1)},
            {"item 2", new myClass(2)},
            {"item 3", new myClass(3)},
            {"item 4", new myClass(4)},
            {"item 5", new myClass(5)},
        }; 

        InitializeComponent();
    }
}

3
x : Name (컴파일러 오류 CS0542)을 변경해야했습니다. 그런 다음 그에 따라 ElementName을 변경해야합니다.
Jack Miller

25

Guy의 대답은 정확하지만 (아마도 10 개 사례 중 9 개에 해당), 이미 DataContext가 스택에 설정되어있는 컨트롤에서이 작업을 수행하려는 경우 DataContext를 설정할 때이를 재설정한다는 점에 유의할 가치가 있습니다. 다시 그 자체로 :

DataContext="{Binding RelativeSource={RelativeSource Self}}"

물론 이것은 기존 바인딩을 깨뜨릴 것입니다.

이 경우 부모가 아닌 바인딩하려는 컨트롤에 RelativeSource를 설정해야합니다.

즉, UserControl의 속성에 바인딩하는 경우 :

Binding Path=PropertyName, 
        RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}

현재 데이터 바인딩에서 무슨 일이 일어나고 있는지 확인하는 것이 얼마나 어려울 수 있는지 감안할 때 현재 설정이 RelativeSource={RelativeSource Self}작동 하는 경우에도이를 염두에 두는 것이 좋습니다. :)


1
Silverlight 4는 FindAncestor를 지원하지 않습니다. 그러나이 사이트에 설명 된대로 FindAncestor를 구현할 수있는 방법으로 수행해야합니다. http://blog.thekieners.com/2010/09/08/relativesource-binding-with-findancestor-mode-in-silverlight/
ShawnFeatherly

6

좀 더 설명 : 'get', 'set'이없는 속성은 바인딩 할 수 없습니다.

나는 질문자 사건처럼 사건에 직면하고있다. 바인드가 제대로 작동하려면 다음 사항이 있어야합니다.

//(1) Declare a property with 'get','set' in code behind
public partial class my_class:Window {
  public String My_Property { get; set; }
  ...

//(2) Initialise the property in constructor of code behind
public partial class my_class:Window {
  ...
  public my_class() {
     My_Property = "my-string-value";
     InitializeComponent();
  }

//(3) Set data context in window xaml and specify a binding
<Window ...
DataContext="{Binding RelativeSource={RelativeSource Self}}">
  <TextBlock Text="{Binding My_Property}"/>
</Window>

9
어떻게 'get'과 'set'없이 속성을 가질 수 있습니까? 그것은 재산이 아니라 필드가 아닐까요?
kjbartel 2014 년

1

변환기 정의 :

public class RowIndexConverter : IValueConverter
{
    public object Convert( object value, Type targetType,
                           object parameter, CultureInfo culture )
    {
        var row = (IDictionary<string, object>) value;
        var key = (string) parameter;
        return row.Keys.Contains( key ) ? row[ key ] : null;
    }

    public object ConvertBack( object value, Type targetType,
                               object parameter, CultureInfo culture )
    {
        throw new NotImplementedException( );
    }
}

사전의 사용자 정의 정의에 바인딩합니다. 생략 한 재정의가 많지만 값이 변경되면 속성 변경 이벤트를 내보내므로 인덱서가 중요합니다. 이는 소스 대 대상 바인딩에 필요합니다.

public class BindableRow : INotifyPropertyChanged, IDictionary<string, object>
{
    private Dictionary<string, object> _data = new Dictionary<string, object>( );

    public object Dummy   // Provides a dummy property for the column to bind to
    {
        get
        {
            return this;
        }
        set
        {
            var o = value;
        }
    }


    public object this[ string index ]
    {
        get
        {
            return _data[ index ];
        }
        set
        {
            _data[ index ] = value;
            InvokePropertyChanged( new PropertyChangedEventArgs( "Dummy" ) ); // Trigger update
        }
    }


}

.xaml 파일에서이 변환기를 사용하십시오. 먼저 참조하십시오.

<UserControl.Resources>
    <ViewModelHelpers:RowIndexConverter x:Key="RowIndexConverter"/>
</UserControl.Resources>

예를 들어 사전에 키가 "이름"인 항목이있는 경우 여기에 바인딩하려면 다음을 사용하십시오.

<TextBlock  Text="{Binding Dummy, Converter={StaticResource RowIndexConverter}, ConverterParameter=Name}">

1

속성 "windowname"을 DependencyProperty로 만들고 나머지는 동일하게 유지합니다.


0

코드 숨김에서 창의 DataContext를 사전으로 설정하십시오. XAML에서 다음을 작성할 수 있습니다.

<ListView ItemsSource="{Binding}" />

이것은 ListView를 사전에 바인딩합니다.

더 복잡한 시나리오의 경우 이는 MVVM 패턴 뒤에있는 기술의 하위 집합입니다 .


0

한 가지 방법은 ObservableCollection (System.Collections.ObjectModel)을 만들고 거기에 사전 데이터를 포함하는 것입니다. 그런 다음 ObservableCollection을 ListBox에 바인딩 할 수 있어야합니다.

XAML에는 다음과 같은 것이 있어야합니다.

<ListBox ItemsSource="{Binding Path=Name_of_your_ObservableCollection" />

0

나는이 똑같은 문제를 겪고 있었지만 지역 변수를 설정했기 때문이 아니 었습니다 ... 나는 자식 창에 있었고 방금 Window XAML에 추가 한 상대 DataContext를 설정해야했습니다.

<Window x:Class="Log4Net_Viewer.LogItemWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    Title="LogItemWindow" Height="397" Width="572">

0

x : Reference 트릭을 시도 할 수 있습니다.

<Window ... x:Name="myWindow"><ListBox ItemsSource="{Binding Items, Source={x:Reference myWindow}}" /></Window>

0

이것이 코드 뒤에 바인딩하는 방법입니다 (property 참조 DataTemplateSelector).

public partial class MainWindow : Window
{
  public MainWindow()
  {
    this.DataTemplateSelector = new MyDataTemplateSelector();

    InitializeComponent();

    // ... more initializations ...
  }

  public DataTemplateSelector DataTemplateSelector { get; }

  // ... more code stuff ...
}

XAML에서는 RelativeSource을 포함하는 Ancestors 를 통해 참조 Window되므로 Window클래스에 있으며 Path선언을 통해 속성을 사용합니다 .

<GridViewColumn Header="Value(s)"
                CellTemplateSelector="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataTemplateSelector}"/>

DataTemplateSelector호출 전 속성 설정은 InitializeComponent구현 누락 IPropertyChanged또는 구현 사용에 따라 달라 지므로 DependencyProperty속성 변경시 통신이 실행되지 않습니다 DataTemplateSelector.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.