어떻게 사용하 WPF 바인딩을 가진 RelativeSource?
-
01-07-2019 - |
문제
어떻게 사용 RelativeSource
WPF 바인딩은 무엇을 사용하여 다양한 사용 사례?
해결책
에 바인딩하려면 다른 속에서 개체:
{Binding Path=PathToProperty, RelativeSource={RelativeSource Self}}
을 얻고 싶은 경우 속성에서는 상위 항목:
{Binding Path=PathToProperty,
RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}
을 얻고 싶은 경우에는 숙박 시설에 템플릿 부모(그래서 당신이 할 수있는 2 가지의 방법인에서 테마 리소)
{Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}}
거나,짧은(이만 작품에 대한 OneWay 바인딩):
{TemplateBinding Path=PathToProperty}
다른 팁
Binding RelativeSource={
RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemType}
}
...
기본 속성 RelativeSource
가 Mode
을 제공합니다.완전한 설정의 유효한 값을 주고 있습니다(에서 MSDN):
PreviousData 수 바인딩하려면 이전의 데이터 항목(지 않을 제어하는 데이터가 포함된 항목)목록에서의 데이터 항목이 표시됩니다.
TemplatedParent 참조하는 요소는 템플릿에서(데이터 바인딩 요소가 존재하는)이 적용됩니다.이것은 비슷한 설정 TemplateBindingExtension 과는 경우에만 적용 바인딩에서는 템플릿입니다.
셀프 참조하는 요소를 설정하는 바인딩을 할 수 바인딩 하나의 속성 요소를 다른 숙박 시설에 같은 요소입니다.
FindAncestor 말 조상도 부모의 체인 데이터 바인딩 요소입니다.당신이 사용할 수 있는 이 바인딩하는 조상에 특정 유형의 또는 그것의 하위 클래스.이 모드를 사용하려는 경우 지정 AncestorType 및/또는 AncestorLevel.
여기에 더 많은 시각적 설명의 컨텍스트에서된 이링
이 경우,사각형을 그리는 그 높이가 항상 그리고 그것의 폭,광장이 말하자.우리가 할 수 있을 사용하여 이를 요소는 이름
<Rectangle Fill="Red" Name="rectangle"
Height="100" Stroke="Black"
Canvas.Top="100" Canvas.Left="100"
Width="{Binding ElementName=rectangle,
Path=Height}"/>
하지만 위의 경우할 의무가 있습을 나타내의 이름 바인딩체,즉 사각형입니다.우리에 도달 할 수 있습 같은 목적으로 다르게 사용하 RelativeSource
<Rectangle Fill="Red" Height="100"
Stroke="Black"
Width="{Binding RelativeSource={RelativeSource Self},
Path=Height}"/>
는 경우 우리는지 의무의 이름을 언급하는 바인딩체 및 폭 항상 동일한 높이할 때마다 높이 변경되었습니다.
하려는 경우 매개 변수할 수 있도록 폭의 절반 높이 그런 다음 이를 수행할 수 있습을 추가하여 변환기를 바인딩 태그를 확장.자 상상이 다른 경우 지금:
<TextBlock Width="{Binding RelativeSource={RelativeSource Self},
Path=Parent.ActualWidth}"/>
위의 경우는 사용하는 넥타이어의 속성 지정된 요소 중 하나에 직접적인 부모들이 요소가 보유하는 시설이라고 합니다.이것은 우리들을 다른 상대 소스 모드는 FindAncestor 하나입니다.
Bechir Bejaoui 노출의 사용 사례를 RelativeSources WPF 에 여기에 자신의 문서:
RelativeSource 마크업 확장에서 사용되는 특정 바인딩을 경우려고 노력하는 것이 우리가 바인드의 속성 지정된체 다른 숙박 시설의 개체,려고 노력하는 것이 우리가 바인딩 제공 의 개체를 또 다른 하나의 상대적,부모님 때 바인딩 종속성 속성 값을 조각의 XAML 의 경우에는 사용자 정의 컨트롤 개발 및 마지막으로 사용하는 경우에는 차이의 시리즈 바인딩된 데이터입니다.모든 사람들의 상황은 표현으로 상대원 니다.내가 노출됩니다 모든 이러한 경우 중 하나에 의해 하나입니다.
- 드 자체:
이 경우,사각형은 우리가 원하는 그것의 높이는 항상 그리고 그것의 폭,광장이 말하자.우리가 할 수 있는 이를 사용하는 요소의 이름을
<Rectangle Fill="Red" Name="rectangle" Height="100" Stroke="Black" Canvas.Top="100" Canvas.Left="100" Width="{Binding ElementName=rectangle, Path=Height}"/>
하지만 위의 경우할 의무가 있습을 나타내는 이름 바인딩체,즉 사각형입니다.우리에 도달 할 수 있습 같은 목적 다르게 사용하 RelativeSource
<Rectangle Fill="Red" Height="100" Stroke="Black" Width="{Binding RelativeSource={RelativeSource Self}, Path=Height}"/>
는 경우 우리는지 의무의 이름을 언급하는 바인딩 체 및 폭 항상 동일한 높이할 때마다 높이 변경되었습니다.
하려는 경우 매개 변수할 수 있도록 폭의 절반 높이 다음 이렇게 할 수 있습을 추가하여 변환기를 바인딩 태그를 확장.자 상상이 다른 경우 지금:
<TextBlock Width="{Binding RelativeSource={RelativeSource Self}, Path=Parent.ActualWidth}"/>
위의 경우는 사용하는 넥타이어의 속성 지정된 요소를 하나의 그것의 직접적인 부모들이 요소를 보유하고 있는 재산 라고 부모입니다.이것은 우리들을 다른 상대 소스 모드가 이 FindAncestor 하나입니다.
- 모 FindAncestor
이 경우에,재산의 지정된 요소를 연결할 수 있는 하나의 그것의 부모님의 Corse.의 주요 차이점으로 위의 경우 사실이 는,그것은 당신이 결정하는 상위 항목을 입력 및 조상 순위 계층에서 넥타이를 제공합니다.방법으로도 재생 이 작품의 XAML
<Canvas Name="Parent0"> <Border Name="Parent1" Width="{Binding RelativeSource={RelativeSource Self}, Path=Parent.ActualWidth}" Height="{Binding RelativeSource={RelativeSource Self}, Path=Parent.ActualHeight}"> <Canvas Name="Parent2"> <Border Name="Parent3" Width="{Binding RelativeSource={RelativeSource Self}, Path=Parent.ActualWidth}" Height="{Binding RelativeSource={RelativeSource Self}, Path=Parent.ActualHeight}"> <Canvas Name="Parent4"> <TextBlock FontSize="16" Margin="5" Text="Display the name of the ancestor"/> <TextBlock FontSize="16" Margin="50" Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Border}, AncestorLevel=2},Path=Name}" Width="200"/> </Canvas> </Border> </Canvas> </Border> </Canvas>
위의 상황은 두 개의 TextBlock 요소들은 임베디드 내 일련의 테두리 및 캔버스에 요소가 그들 자신의 나라를 대표 계층적 부모이다.두 번째 TextBlock 의 이름이 표시됩 주어진 부모에 상대적인 원 수준입니다.
그래서를 변경하려고 AncestorLevel=2AncestorLevel=1 조 이 발생합니다.음의 유형을 변경하려면 조상에서 AncestorType=국경을 AncestorType=캔버스에 무엇을 볼 발생합니다.
표시된 텍스트가 변화에 따라 조상과 유형 수준입니다.그럼 무슨 일이 일어날 경우에 조상의 수준은 적합하지 않은 조상의 유형은?이 좋은 질문입니다,나는 당신 구합니다.응답이 없는 예외가 발생하고 아무것도 아닌 것입니다 에 표시되 TextBlock 수준입니다.
- TemplatedParent
이 모드에서는 타이 특정 테마 리소 시설을 제공 의 통제되는 테마 리소이 적용됩니다.아 문제를 이해하기는 여기를 들어 벨
<Window.Resources> <ControlTemplate x:Key="template"> <Canvas> <Canvas.RenderTransform> <RotateTransform Angle="20"/> </Canvas.RenderTransform> <Ellipse Height="100" Width="150" Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}"> </Ellipse> <ContentPresenter Margin="35" Content="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Content}"/> </Canvas> </ControlTemplate> </Window.Resources> <Canvas Name="Parent0"> <Button Margin="50" Template="{StaticResource template}" Height="0" Canvas.Left="0" Canvas.Top="0" Width="0"> <TextBlock FontSize="22">Click me</TextBlock> </Button> </Canvas>
내가 원하는 경우 적용의 속성 주어진 제어하는 제어 템플릿은 다음을 사용할 수 있습니다 TemplatedParent 모니다.도 비슷한 이 마크업 확장자는 TemplateBinding 일종의 짧은 손으로의 첫 번째 중 하나하지만, TemplateBinding 평가에서 컴파일에서 시간의 대비 TemplatedParent 는 평가한 후 처음 실행 시간입니다.로 할 수 있는 발언에서는 아래 그림,배경과 내용 에 적용되 내에서 버튼을 통제 템플릿입니다.
에 WPF RelativeSource
바인딩을 노출하 세 properties
을 설정:
1.모: 이 enum
수있는 네 개의 값:
니다.PreviousData(
value=0
): 그것은 할당 이전 값의property
하기 은 하나밖에 없b.TemplatedParent(
value=1
): 할 수 없을 때 사용됩니다.정의templates
의 모든 제어와 원하는 바인딩하는 값이/성control
.예를 들어, 정의
ControlTemplate
:
<ControlTemplate>
<CheckBox IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</ControlTemplate>
c.셀프(
value=2
): 때 우리가 원하는 바인딩에서self
나property
의 자체입니다.예를 들어: 보내의 상태 검사
checkbox
로CommandParameter
설정하는 동안Command
에CheckBox
<CheckBox ...... CommandParameter="{Binding RelativeSource={RelativeSource Self},Path=IsChecked}" />
d.FindAncestor(
value=3
): 을 때에 바인딩하려서 부모로control
에Visual Tree
.예를 들어: 바인딩
checkbox
에records
는 경우grid
는 경우header
checkbox
검사
<CheckBox IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type iDP:XamDataGrid}}, Path=DataContext.IsHeaderChecked, Mode=TwoWay}" />
2.AncestorType: 우 모드 FindAncestor
를 정의 어떤 유형의 조상
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type iDP:XamDataGrid}}
3.AncestorLevel: 우 모드 FindAncestor
그런 다음 어떤 수준의 조상(이 있는 경우 같은 두 가지 유형의 부모에 visual tree
)
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type iDP:XamDataGrid, AncestorLevel=1}}
위의 모든 사용 사례에 대한
RelativeSource binding
.
는 것을 잊지 않 TemplatedParent:
<Binding RelativeSource="{RelativeSource TemplatedParent}"/>
나
{Binding RelativeSource={RelativeSource TemplatedParent}}
그것은 노트의 가치는 사람들을 위해 걸림돌에서 이 생각의 Silverlight:
Silverlight 제공하는 감소한 하위 집합을만,이러한 명령
내가 만들어 라이브러리를 단순화하딩 구문의 WPF 포함하여 사용하기 쉽게 만드는 RelativeSource.여기에 몇 가지 예입니다.기:
{Binding Path=PathToProperty, RelativeSource={RelativeSource Self}}
{Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}
{Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}}
{Binding Path=Text, ElementName=MyTextBox}
후:
{BindTo PathToProperty}
{BindTo Ancestor.typeOfAncestor.PathToProperty}
{BindTo Template.PathToProperty}
{BindTo #MyTextBox.Text}
여기에는 예입니다 바인딩 방법을 간략하게 되었습니다.기:
// C# code
private ICommand _saveCommand;
public ICommand SaveCommand {
get {
if (_saveCommand == null) {
_saveCommand = new RelayCommand(x => this.SaveObject());
}
return _saveCommand;
}
}
private void SaveObject() {
// do something
}
// XAML
{Binding Path=SaveCommand}
후:
// C# code
private void SaveObject() {
// do something
}
// XAML
{BindTo SaveObject()}
당신을 찾을 수 있습니다 라이브러리는 여기: http://www.simplygoodcode.com/2012/08/simpler-wpf-binding.html
참고에서'앞에'예제는 내가 사용하는 방법에 대한 바인딩하는 코드는 이미 이용하여 최적화 RelayCommand
는 마지막으로 내가 확인되지 않는 기본 부품의 WPF.지 않고는'전'예되었습니다.
몇 가지 유용한 조각:
여기에서 그것을 어떻게 대부분에 코드:
Binding b = new Binding();
b.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, this.GetType(), 1);
b.Path = new PropertyPath("MyElementThatNeedsBinding");
MyLabel.SetBinding(ContentProperty, b);
내가 크게에서 이것을 복사 바인딩에 상대적 근원에서 뒤에 코드.
또한,MSDN 페이지가 꽤 좋은 멀리로 예를 이동: RelativeSource 클래스
나는 그냥 게시 다른 솔루션 액세스하기 위한 매핑되는 부모의 요소에 Silverlight 있습니다.그것은 사용 Binding ElementName
.
를 읽지 않았는 모든 답변을,하지만 난 그냥을 추가하려는 이 정보의 경우에는 상대적인 원본 명령의 결합니다.
을 사용할 때 상대원 Mode=FindAncestor
, 바인딩처럼 되어야 합니다:
Command="{Binding Path=DataContext.CommandProperty, RelativeSource={...}}"
를 추가하지 않으면 매핑되는 경로에서 실행 시간에 그것을 검색할 수 없습니다.
이것은 예를 들어 사용이 패턴의하는 나를 위해 일 빈에서 datagrids.
<Style.Triggers>
<DataTrigger Binding="{Binding Items.Count, RelativeSource={RelativeSource Self}}" Value="0">
<Setter Property="Background">
<Setter.Value>
<VisualBrush Stretch="None">
<VisualBrush.Visual>
<TextBlock Text="We did't find any matching records for your search..." FontSize="16" FontWeight="SemiBold" Foreground="LightCoral"/>
</VisualBrush.Visual>
</VisualBrush>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
는 경우 요소의 일부가 아닙니다 visual 트리,그 RelativeSource 작동 하지 않습니다.
이 경우에,당신은 필요 시 다른 기술을 개척하여 토마스 Levesque.
그는 솔루션을에서는 그의 블로그에서 [WPF]에 바인딩하는 방법을 때 데이터 매핑되는 상속되지 않습니다.고 그것은 작품을 절대적으로 훌륭하게!
지 않을 경우에는 그의 블로그가 아래로,부록 A 담 거울본 자신의 문서.
언급하지 마십시오 여기십시오 댓글을 직접 자신의 블로그에 포스트.
부록 A:울의 블로그에 포스트
이 매핑되는 숙박 시설에 WPF 은 매우 편리하기 때문에,그것은 자동으로 상속으로 모든 어린이의 요소 할당한다;따라서 당신은 설정할 필요가 없이 그것을 다시 각 요소에 대해 당신이 원하는 바인딩.그러나 어떤 경우에 매핑되지 않은 액세스 할 수 있습니다:그것은 발생 요소에 대한되지 않는 부분의 시각적 또는 논리적인 나무입니다.그것은 매우 어려울 수 있습니다 그 다음에 바인딩하는 속에서 이러한 요소...
을 설명하자는 간단한 예제:우리의 목록을 표시하려면 제품에 DataGrid.에서 그리드,우리가 할 수 있 표시하거나 가격을 숨기는 열에 기반한 가치의 ShowPrice 속성에 의해 노출된 뷰 모델.다음 방법을 사용할 수 있습니다 바인딩 가시성 의 열 ShowPrice 속성:
<DataGridTextColumn Header="Price" Binding="{Binding Price}" IsReadOnly="False"
Visibility="{Binding ShowPrice,
Converter={StaticResource visibilityConverter}}"/>
불행하게도,값 변경 ShowPrice 효과가 없고 열가 항상 표시되는 이유는?면 우리는 출력에서 창 Visual Studio 에서,우리는 다음 사항을 확인합니다 라인:
시스템입니다.Windows.데이터 오류가:2:을 찾을 수 없는 관 FrameworkElement 또는 frameworkcontentelement 에 대한 대상 요소입니다.BindingExpression:Path=ShowPrice;DataItem=null;대상 요소입니다'DataGridTextColumn'(차=32685253);대상 시설은'가시성'(유형'가시성')
메시지가 오히려한,그러나 의미입니다 실제로 아주 간단하다:WPF 알지 못하는 FrameworkElement 사용하를 얻을 매핑되기 때문에 열에 속하지 않은 시각적 또는 논리 나무의 DataGrid.
우리도 할 수 있습을 조정할 수 바인딩을 원하는 결과를 얻기 위해 예를 들어,설정 RelativeSource DataGrid 자체:
<DataGridTextColumn Header="Price" Binding="{Binding Price}" IsReadOnly="False"
Visibility="{Binding DataContext.ShowPrice,
Converter={StaticResource visibilityConverter},
RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}}"/>
나를 추가할 수 있습니다란 바 ShowPrice,과에 바인딩하려고 열시 공용 속성을 지정하는 요소로 이름:
<DataGridTextColumn Header="Price" Binding="{Binding Price}" IsReadOnly="False"
Visibility="{Binding IsChecked,
Converter={StaticResource visibilityConverter},
ElementName=chkShowPrice}"/>
그러나 아무도 이러한 대안을 작동하는 것 같다,우리는 항상 같은 결과를 얻을...
이 시점에서,그것은 보인다는 가능한 유일한 방법 것을 변경하는 열성 코드에서 뒤에,우리는 일반적으로 선호하는 경우를 피하기 위해 사용된 이 패턴...그러나 나는 포기하지 않도록 즉시 적어도 있는 동안은 다른 옵션을 고려할😉
해결책은 우리의 문제는 실제로 아주 간단하고 활용하 Freezable 클래스입니다.기본 목적은 이 클래스의 정의가 있는 개체를 수정할 수 있고 읽기-유일한 국가이지만,흥미로운 기능은 우리의 경우에는 Freezable 개체할 수 있는 상속에 매핑되는 경우에도 그들이 시각적 또는 논리적인 나무입니다.나는 알 수 없는 정확한 메커니즘이 이를 가능하게 하는 행동,하지만 우리는 그것을 활용하여 확인 우리의 바인딩이다.
아이디어는 클래스를 만들(나는 그것 BindingProxy 한 이유는 명백하게 되는 곧)상속되는 Freezable 및 선언하는 데이터는 종속성 속성:
public class BindingProxy : Freezable
{
#region Overrides of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}
우리는 할 수 있음을 선언하는 이 클래스의 인스턴스에서의 자원 DataGrid 바 데이터를 제공하는 현재 매핑되:
<DataGrid.Resources>
<local:BindingProxy x:Key="proxy" Data="{Binding}" />
</DataGrid.Resources>
마지막 단계입니다 이를 지정하 BindingProxy 체(쉽게 액세스할 수 있으로 StaticResource)으로 원인:
<DataGridTextColumn Header="Price" Binding="{Binding Price}" IsReadOnly="False"
Visibility="{Binding Data.ShowPrice,
Converter={StaticResource visibilityConverter},
Source={StaticResource proxy}}"/>
참고하는 바인딩을 경로를 붙"Data"때문에,경로가 지금 상대 BindingProxy 개체입니다.
바인딩을 지금 제대로 작동하고,열의가 제대로 표시하거나 숨겨진 기반으로 ShowPrice 을 제공합니다.