Pregunta

¿Cómo puedo obligar a la propiedad de un UserControl desde el interior de su ResourceDictionary? Quiero un objeto declaro en mis recursos tenga la misma DataContext como el UserControl está contenida en:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Some.Namespace"
    DataContext="{Binding Path=ViewModel, RelativeSource={RelativeSource Self}}">
    <UserControl.Resources>
        <local:SomeClass
            x:Key="SomeClass"
            DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
    </UserControl.Resources>
</UserControl>

En tiempo de ejecución se produce el error:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='UserControl', AncestorLevel='1''. BindingExpression:Path=DataContext; DataItem=null; target element is 'SomeClass' (Name=''); target property is 'DataContext' (type 'Object')

¿Fue útil?

Solución

Mi solución fue establecer la DataContext del recurso en el código subyacente.

.xaml

<local:SomeType x:Key="SomeKey" SomeProperty="{Binding ... }" />

.xaml.cs

public SomeControl()
{
    InitializeComponent();
    ((SomeType)this.Resources["SomeKey"]).DataContext = this;
}

Otros consejos

Cuando se utiliza FindAncestor, el elemento de destino debe ser un descendiente (ya sea lógica o visual) de la fuente. Su objeto no aparece ni en el árbol visual o lógico, es simplemente en los recursos. Por lo tanto no se puede utilizar con RelativeSource FindAncestor para su objeto.

Puede utilizar ElementName en su Encuadernación sin embargo. Algo como esto debería funcionar:

<UserControl x:Name="userControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Some.Namespace"
    DataContext="{Binding Path=ViewModel, RelativeSource={RelativeSource Self}}">
    <UserControl.Resources>
        <local:SomeClass
            x:Key="SomeClass"
            DataContext="{Binding Path=DataContext, ElementName=userControl}" />
    </UserControl.Resources>
</UserControl>

x: Compartido = "falso", esto va a clonar recurso en cada uso y hacer que un niño de su elemento, lo que permite el uso de enlaces.

<local:SomeClass
            x:Key="SomeClass"
            x:Shared="False"
            DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />

Creo que lo que estás buscando es simplemente {Binding} que se une a la DataContext heredada. He aquí un ejemplo, aunque un poco extraños muestra cómo se puede tomar un color a través de la unión a la DataContext:

<Window x:Class="AncestorBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <SolidColorBrush x:Key="MyBrush" Color="Blue" />
    </Window.Resources>
    <StackPanel>
        <Button DataContext="{Binding Source={StaticResource MyBrush}}" Content="My Button">
            <Button.Resources>
                <Style TargetType="{x:Type Button}">
                    <Setter Property="Background" Value="{Binding}" />
                </Style>
            </Button.Resources>
        </Button>
    </StackPanel>
</Window>

Lo que yo haría es crear un comportamiento adjunto (ContextualizeResourceBehavior) en el control de usuario y especificar la clave de recursos en ese comportamiento adjunto. El comportamiento sería buscar el recurso (no estoy seguro que sería capaz de hacerlo por adjuntar, si no es lo que se necesita para conectar evento Loaded) y transferir el contexto de datos.

cuando se agrega su recurso para el árbol visual debe heredar el contexto de datos. pero ... echar un vistazo a espía elemento que sólo podría hacer lo que necesita.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top