2009-02-03 11 views
7

J'ai créé un contrôle utilisateur dans WPF:Comment lire un paramètre passé dans un UserControl WPF?

<UserControl x:Class="TestUserControl.Controls.GetLatest" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
     <TextBlock Name="theTextBlock"/> 
</UserControl> 

Le code a derrière un paramètre appelé "FirstMessage", qui définit comme le texte de mon TextBlock de contrôle de l'utilisateur:

public partial class GetLatest : UserControl 
{ 
    public string FirstMessage { get; set; } 

    public GetLatest() 
    { 
     InitializeComponent(); 
     theTextBlock.Text = this.FirstMessage; 
    } 
} 

Dans mon code principal Je peux régler le paramètre FirstMessage dans mon contrôle utilisateur avec IntelliSense:

<Window x:Class="TestUserControl.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" 
    xmlns:controls="clr-namespace:TestUserControl.Controls" 
    > 
    <StackPanel> 
     <controls:GetLatest FirstMessage="This is the title"/> 
    </StackPanel> 
</Window> 

Cependant, cela ne fonctionne toujours pas défini le texte. J'ai essayé Text = "{Binding Path = FirstMessage}" et d'autres syntaxes que j'ai trouvées mais rien ne fonctionne.

Comment puis-je accéder à la valeur FirstMessage dans mon contrôle utilisateur?

Répondre

15

Votre approche de la liaison ne fonctionne pas car votre propriété FirstMessage ne le notifie pas lorsqu'elle est mise à jour. Utilisez les propriétés de dépendance pour cela. Voir ci-dessous:

public partial class GetLatest : UserControl 
{ 
    public static readonly DependencyProperty FirstMessageProperty = DependencyProperty.Register("FirstMessage", typeof(string), typeof(GetLatest)); 

    public string FirstMessage 
    { 
     get { return (string)GetValue(FirstMessageProperty); } 
     set { SetValue(FirstMessageProperty, value); } 
    } 

    public GetLatest() 
    { 
     InitializeComponent(); 
     this.DataContext = this; 
    } 

} 

XAML:

<UserControl x:Class="TestUserControl.Controls.GetLatest" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <TextBlock Text="{Binding FirstMessage}" /> 
</UserControl> 

Chaque fois que la propriété change FirstMessage, votre bloc de texte se mettra à jour.

+0

oui! exactement ce que je cherchais, merci! –

+0

J'ai essayé votre solution et j'ai obtenu l'erreur "Profondeur de l'arbre logique dépassée lors de la traversée de l'arbre, ce qui pourrait indiquer un cycle dans l'arbre." mais quand je supprime la ligne this.DataContext = this; l'erreur disparaît mais la liaison ne fonctionnera pas. Quel est le problème ici? –

+0

@Tri Q: Je vois aussi l'exception de profondeur d'arbre logique mais dans un code différent. Ne semble pas être beaucoup de matériel concernant cette erreur sur le Web, donc je suis curieux de savoir si vous pourriez répondre si vous avez trouvé une solution. – jpierson

3

FirstMessage est défini après l'appel du constructeur. Vous devriez changer votre texte du setter de FirstMessage. Lors de l'initialisation d'un objet à partir de XAML, le constructeur par défaut est appelé, puis les propriétés sont définies sur l'objet.

0

Dans le cas du code que vous avez posté ci-dessus, il s'agit d'un problème de synchronisation; la valeur de la propriété FirstMessage n'a pas été affectée lors de l'exécution du constructeur. Vous devrez exécuter ce code dans un événement survenant plus tard, tel que Loaded.

2

Cet exemple rapide n'utilisera aucune liaison car la valeur n'est pas définie avant l'appel du constructeur par défaut, mais voici comment vous pouvez afficher le texte.

<UserControl x:Class="TestUserControl.Controls.GetLatest" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Loaded="GetLatest_Loaded"> 
     <TextBlock Name="theTextBlock"/> 
</UserControl> 

Ensuite, il suffit de modifier votre fichier cs à ceci:

public partial class GetLatest : UserControl 
{ 
    public string FirstMessage { get; set; } 

    public GetLatest() 
    { 
     InitializeComponent(); 
     theTextBlock.Text = this.FirstMessage; 
    } 

    private void GetLatest_Loaded(object sender, RoutedEventArgs e) 
    { 
     theTextBlock.Text = this.FirstMessage; 
    } 
} 

Je recommande de travailler sur la mise en place à la place d'une liaison, car cela est assez code spaghetti.

1

Vous pouvez également utiliser:

public partial class GetLatest : UserControl 
{ 
    private string _firstMessage; 
    public string FirstMessage 
    { 
     get { return _firstMessage; } 
     set { _firstMessage = value; theTextBlock.Text = value; } 
    } 

    public GetLatest() 
    { 
     InitializeComponent(); 
    } 
} 
Questions connexes