[c#] 코드 숨김에 정의 된 바인딩 개체

예를 들어 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”가되어야한다고 가정하겠습니다. 맞습니까? 하지만 아무것도 보여주지 않습니다.



답변

다음과 같이 컨트롤, 양식 등에 대한 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 속성에 직접 바인딩 할 수 있어야합니다. 창문에.


답변

이 작업을 수행하는 훨씬 쉬운 방법이 있습니다. 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();
    }
}


답변

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}작동 하는 경우에도이를 염두에 두는 것이 좋습니다. 🙂


답변

좀 더 설명 : ‘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>


답변

변환기 정의 :

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


답변

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


답변

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

<ListView ItemsSource="{Binding}" />

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

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