RelativeSource и Popup

Проблема в том, что RelativeSource не работает в следующем случае. Я использую Silverlight 5.

//From MainPage.xaml
<Grid x:Name="LayoutRoot" Background="White" Height="100" Width="200">
    <Popup IsOpen="True">
        <TextBlock Text="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=Grid}}" />
    </Popup>
</Grid>

//From MainPage.xaml.cs
public MainPage()
{
    InitializeComponent();
    DataContext = "ololo";
}

Если я установлю точку останова на привязку, я получу ошибку:

System.Exception: BindingExpression_CannotFindAncestor.

Если я использую ElementName=LayoutRoot вместо RelativeSource, все будет хорошо.

Почему относительная привязка источника не работает?

4 ответа

Решение

Всплывающее окно похоже на ContextMenu, элементы управления ToolTip, они не добавляются в VisualTree. Для этого вам придется сделать как

<Grid x:Name="LayoutRoot" Height="100" Width="200" Background="Black">
    <Popup Grid.Row="0"  x:Name="popup" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Mode=Self}}">
        <TextBlock Text="{Binding DataContext, ElementName=popup}" Background="Red" Width="30" Height="30" />
    </Popup>
</Grid>

public MainWindow()
    {
        InitializeComponent();
        DataContext = "abcd";
        popup.PlacementTarget = LayoutRoot; 
    }

Я надеюсь, что это поможет. Не так, как в случае с ContextMenu или Tooltip, здесь вам также нужно будет указать PlacementTarget.

Вы можете сделать небольшой взлом: настроить DataContext через ресурсы.

<Grid.Resources>
    <Style TargetType="TextBlock">
        <Setter Property="DataContext" Value="{Binding ElementName=myGrid, Path=DataContext}" />
    </Style>
</Grid.Resources>

Как уже упоминали другие, это потому, что Popup не является частью визуального дерева. Вместо этого вы можете использовать свойство PlacementTarget для возврата к визуальному дереву:

<Grid x:Name="LayoutRoot" Background="White" Height="100" Width="200">
    <Popup IsOpen="True">
        <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Popup}}, 
                                  Path=PlacementTarget.DataContext}" />
    </Popup>
</Grid>

Всплывающие окна не являются частью визуального дерева.

Относительный источник "Получает или задает источник привязки, указывая его местоположение относительно позиции цели привязки (MSDN)". Поскольку всплывающие окна не являются частью визуального дерева отображающего его элемента управления, они не смогут разрешить что-либо за пределами всплывающего окна.

Другие вопросы по тегам