2019년 4월 15일 월요일

WPF - Binding Proxy

WPF에서 DataContext 속성은 할당된 요소의 자식에게 자동으로 상속되므로 편리하다. 따라서 바인딩하려는 각 요소에 대해 다시 DataContext를 지정하지 않아도 된다.

그러나 WPF에서 바인딩 대상이 Target Object와 다르거나 Visual Tree가 다른 경우 참조식을 작성할 때 불필요하게 식이 길어지는 경우가 종종 있다. (DataGrid, ItemsControl 내 엘리먼트가 ViewModel의 프로퍼티를 참조하는 경우)

이런 상황에 놓이면 사용자가 해당 요소에 DataContext를 직접 알려주어야 한다.
이러한 경우 Binding Proxy를 만들어 이용하면 코드도 간결해지고 표현도 명확해진다.

public class BindingProxy : Freezable
{
    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy));
}

Freezable을 구현하는 까닭은 WPF에서 Freezable 객체는 Visual Tree 또는 Logical Tree가 다른 경우에도 DataContext를 상속할 수 있기 때문이다. 사용법은 아래와 같은데, proxy 객체의 Data attached 프로퍼티에 바인딩 된 뷰모델을 바로 참조할 수 있다. (물론 단순한 경우엔 x:Name ~ x:Reference, RelativeSource ~ FindAncestor가 나을지도 모르겠다.)


    <DataGrid>
        <DataGrid.Resources>
            <local:BindingProxy x:Key="proxy" Data="{Binding}"/>
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Visibility="{Binding Data.MyColumnVisibility,
                                                Source={StaticResource proxy}}"/>
        </DataGrid.Columns>
    </DataGrid>


https://thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/

댓글 없음:

댓글 쓰기