2009-02-03 19 views
7

Ich habe eine Benutzersteuerung in WPF:Wie liest man einen übergebenen Parameter in einem WPF UserControl?

<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> 

Der Code hinter einen Parameter "FirstMessage", die sie als Text meiner Benutzerkontrolle TextBlock- setzt:

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

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

In meinem Haupt-Code ich kann den FirstMessage Parameter in meiner Benutzersteuerung mit Intellisense gesetzt:

<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> 

es ist jedoch immer noch nicht den Text gesetzt. Ich habe versucht, Text = "{Binding Path = FirstMessage}" und andere Syntaxen, die ich gefunden habe, aber nichts funktioniert.

Wie kann ich auf den FirstMessage-Wert in meinem Benutzersteuerelement zugreifen?

Antwort

15

Ihr Ansatz zur Bindung funktioniert nicht, da Ihre Eigenschaft FirstMessage nicht benachrichtigt, wenn sie aktualisiert wird. Verwenden Sie dazu Abhängigkeitseigenschaften. Siehe unten:

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> 

Wann immer die FirstMessage Eigenschaft ändert, Ihr Textblock wird selbst aktualisieren.

+0

ja! Genau das, was ich gesucht habe, danke! –

+0

Ich habe versucht Ihre Lösung und habe den Fehler "Logische Baumtiefe überschritten beim Durchqueren des Baumes. Dies könnte einen Zyklus in der Struktur angeben." aber wenn ich die Zeile entferne this.DataContext = this; Der Fehler verschwindet, aber die Bindung funktioniert nicht. Was ist das Problem hier? –

+0

@Tri Q: Ich sehe die logische Baumtiefe Ausnahme auch, aber in anderem Code. Es scheint nicht viel Material in Bezug auf diesen Fehler im Web zu sein, also bin ich neugierig, ob Sie antworten könnten, wenn Sie eine Lösung gefunden haben. – jpierson

3

FirstMessage wird gesetzt, nachdem der Konstruktor aufgerufen wurde. Sie sollten Ihren Text vom Setter von FirstMessage ändern.

Bei der Initialisierung eines Objekts von XAML wird zuerst der Standardkonstruktor aufgerufen, dann werden die Eigenschaften für das Objekt festgelegt.

0

Bei dem oben angegebenen Code handelt es sich um ein Timing-Problem; Die FirstMessage-Eigenschaft wurde nicht zugewiesen, wenn der Konstruktor ausgeführt wird. Sie müssten diesen Code in einem späteren Ereignis wie Loaded ausführen.

2

Dieses schnelle Beispiel wird keine Bindung verwenden, da der Wert erst nach dem Aufruf des Standardkonstruktors eingerichtet wird, aber hier können Sie den Text anzeigen lassen.

<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> 

Dann ändern Sie einfach Ihre cs-Datei folgendermaßen aus:

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; 
    } 
} 

Ich empfehle arbeiten, anstatt eine Bindung an die Einrichtung, da dies ziemlich spaghettiartigen Code.

1

Sie können auch verwenden:

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

    public GetLatest() 
    { 
     InitializeComponent(); 
    } 
} 
Verwandte Themen