2009-10-28 11 views
22

Attualmente sto lavorando all'interno di un controllo utente WPF (l'elemento radice del mio file XAML è "UserControl"), che so essere ospitato all'interno di una finestra. Come posso accedere a una proprietà della finestra utilizzando l'associazione dati?Che cosa fa esattamente "RelativeSource FindAncestor" di WPF Data Binding?

Qualcuno sa perché semplicemente

<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Window}}" Path="..." /> 

non funziona? Viene visualizzato il messaggio di errore:

System.Windows.Data Avviso: 4: Impossibile trovare l'origine per il collegamento con riferimento 'RelativeSource FindAncestor, AncestorType =' System.Windows.Window ', AncestorLevel =' 1 ''.

Modifica: Ho finito per utilizzare una variazione sull'approccio di ArsenMkrt, quindi ho accettato la sua risposta. Tuttavia, sono ancora interessato a scoprire perché FindAncestor non "funziona".

+2

hai detto che hai variato la sua risposta, puoi pubblicare quello che hai effettivamente fatto? – Miles

+0

Nota che stavo cercando una soluzione a questo problema nel contesto del pattern MVVM. La proprietà della finestra che volevo associare era in realtà una proprietà di ViewModel di Windows. – user200783

+1

ArsenMkrt ha suggerito la creazione di una proprietà in UserControl e l'associazione a tale, quindi a sua volta (in XAML) l'associazione di questa proprietà alla proprietà desiderata della finestra. Con il pattern MVVM, tuttavia, UserControl non appariva mai in XAML, quindi la seconda parte non era possibile. – user200783

risposta

15

Il modo migliore è quello di dare un nome a UserControl

Crea dipendenza proprietà MyProperty in UserControl con il legame a due vie e associarlo nella finestra principale, che si legano in UserControl come questo

<UserControl x:Name = "myControl"> 
    <Label Content={Binding ElementName= myControl, Path=MyProperty}/> 
</UserControl> 
+0

Ma voglio associare a una proprietà nella finestra che lo contiene (definita in un altro file XAML), non in UserControl. – user200783

+0

È meglio avere una proprietà in usercontrol e associare quella proprietà con la proprietà della finestra –

+2

Puoi creare una proprietà di dipendenza in UserControl? non aggiungi il controllo elettronico in finestra?

0

I Think È necessario impostare la modalità = "OneWayToSource" ti piace questa:

<TextBox Text="{Binding RelativeSource={RelativeSource FindAncestor ,AncestorType={x:Type Grid}},Path=BackGround , Mode=OneWayToSource , UpdateSourceTrigger = PropertyChanged}" /> 
4

Se stai cercando di 'fuga' da un ItemsControl o DataGridView per arrivare a un Window potresti scoprire che AncestorType di x:Type Window non funziona. O almeno non sembra ...

Se questo è il caso, probabilmente stai eseguendo Blend o Visual Studio e ti aspetti che i dati siano visibili in fase di progettazione, cosa che non sarà perché VS + fonderà entrambi creare le proprie istanze che non sono realmente Windows. Funzionerà correttamente in runtime, ma non durante la modalità di progettazione.

Ci sono un paio di cose che puoi fare:

  • Avvolgere in un UserControl

  • Ecco una soluzione alternativa mi è venuta in mente. Ha un vantaggio in quanto non stai facendo riferimento a uno UserControl o Window direttamente, quindi se cambi il contenitore genitore il tuo codice non si romperà.

    <Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:views="clr-namespace:MyWPFApplication.Views" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     
    x:Class="MyWPFApplication.Views.UPCLabelPrinterWindow" 
    mc:Ignorable="d" 
    x:Name="LayoutRoot" 
    Title="UPCLabelPrinterWindow"> 
    
    <views:DataContextWrapper> 
        <DockPanel> 
         ... 
        </DockPanel> 
    </views:DataContextWrapper> 
    

Dove DataContextWrapper è solo una griglia

namespace MyWPFApplication.Views { 
    public class DataContextWrapper : Grid 
    { 

    } 
} 

Poi quando si associa si esegue questa operazione:

<TextBlock Text="{Binding="{Binding DataContext.SomeText, 
    RelativeSource={RelativeSource AncestorType={x:Type views:DataContextWrapper}, 
    Mode=FindAncestor}}" /> 

Nota: se si desidera associare a una proprietà sulla stessa finestra è più difficile e probabilmente dovresti eseguire il binding tramite una proprietà di dipendenza o qualcosa del genere. Ma se si utilizza MVVM, questa è una soluzione che ho trovato.

+0

Nel mio caso 'AncestorType = {x: Type Window}' è stato piuttosto utile, perché 'AncestorType = UserControl' in qualche modo non puntava alla mia finestra - sebbene lo faccia normalmente. – LuckyLikey

Problemi correlati