Ich habe eine Reihe von Steuerelementen mit angehängten Befehlen und Logik, die ständig auf die gleiche Weise wiederverwendet werden. Ich habe beschlossen, ein Benutzersteuerelement zu erstellen, das alle gängigen Steuerelemente und die Logik enthält.
Ich benötige jedoch auch das Steuerelement, um benennbare Inhalte enthalten zu können. Ich habe folgendes versucht:
<UserControl.ContentTemplate>
<DataTemplate>
<Button>a reused button</Button>
<ContentPresenter Content="{TemplateBinding Content}"/>
<Button>a reused button</Button>
</DataTemplate>
</UserControl.ContentTemplate>
Es scheint jedoch, dass Inhalte, die sich im Benutzersteuerelement befinden, nicht benannt werden können. Zum Beispiel, wenn ich das Steuerelement folgendermaßen verwende:
<lib:UserControl1>
<Button Name="buttonName">content</Button>
</lib:UserControl1>
Ich erhalte folgende Fehlermeldung:
Der Name-Attributwert 'buttonName' kann für das Element 'Button' nicht festgelegt werden. 'Button' befindet sich im Bereich des Elements 'UserControl1', für das bereits ein Name registriert war, als er in einem anderen Bereich definiert wurde.
Wenn ich den ButtonName entferne, wird er kompiliert, ich muss jedoch in der Lage sein, den Inhalt zu benennen. Wie kann ich das erreichen?
Antworten:
Die Antwort ist, kein UserControl zu verwenden, um dies zu tun.
Erstellen Sie eine Klasse, die ContentControl erweitert
Verwenden Sie dann einen Stil, um den Inhalt anzugeben
und schließlich - benutze es
quelle
UserControl
in geerbt geändertContentControl
. Fügen Sie zum Lösen einfach eine neue Klasse hinzu ( nicht XAML mit CS). Und dann wird es (hoffentlich) funktionieren. Wenn Sie möchtenHeadingContainer
undMyFunkyContainer
soll seinMyFunkyControl
?!Es scheint, dass dies nicht möglich ist, wenn XAML verwendet wird. Benutzerdefinierte Steuerelemente scheinen ein Overkill zu sein, wenn ich tatsächlich alle Steuerelemente habe, die ich benötige, sie aber nur mit ein wenig Logik gruppieren und benannte Inhalte zulassen muss.
Die Lösung auf JDs Blog, wie Mackenir vorschlägt, scheint den besten Kompromiss zu haben. Eine Möglichkeit, die Lösung von JD zu erweitern, damit Steuerelemente weiterhin in XAML definiert werden können, könnte folgende sein:
In meinem obigen Beispiel habe ich ein Benutzersteuerelement mit dem Namen UserControlDefinedInXAML erstellt, das wie alle normalen Benutzersteuerelemente mit XAML definiert ist. In meiner UserControlDefinedInXAML habe ich ein StackPanel namens aStackPanel, in dem mein benannter Inhalt angezeigt werden soll.
quelle
Eine andere Alternative, die ich verwendet habe, besteht darin, die
Name
Eigenschaft imLoaded
Ereignis festzulegen.In meinem Fall hatte ich ein ziemlich komplexes Steuerelement, das ich nicht im CodeBehind erstellen wollte, und es suchte nach einem optionalen Steuerelement mit einem bestimmten Namen für ein bestimmtes Verhalten, und da ich bemerkte, dass ich den Namen in a setzen konnte
DataTemplate
Ich dachte, ich könnte es auch in diesemLoaded
Fall tun .quelle
Manchmal müssen Sie möglicherweise nur auf das Element aus C # verweisen. Abhängig vom Anwendungsfall können Sie dann ein
x:Uid
anstelle vonx:Name
und festlegen und auf die Elemente zugreifen, indem Sie eine Uid-Finder-Methode wie Get object by its Uid in WPF aufrufen .quelle
Sie können diesen Helfer für den Set-Namen innerhalb des Benutzersteuerelements verwenden:
und Ihr Fenster oder Steuercode dahinter legen Sie die Kontrolle über die Eigenschaft fest:
Ihr Fenster xaml:
UserControlNameHelper ruft Ihren Steuerelementnamen und Ihren Klassennamen ab, um Control auf Property zu setzen.
quelle
Ich habe beschlossen, für jedes Element, das ich erhalten möchte, eine zusätzliche Eigenschaft zu erstellen:
Dadurch kann ich auf die untergeordneten Elemente in XAML zugreifen:
quelle
Code dahinter:
Die wirkliche Lösung wäre, dass Microsoft dieses Problem sowie alle anderen mit gebrochenen visuellen Bäumen usw. behebt. Hypothetisch gesehen.
quelle
Noch eine Problemumgehung: Verweisen Sie auf das Element als RelativeSource .
quelle
Ich hatte das gleiche Problem mit einem TabControl, als ich eine Reihe benannter Steuerelemente in platzierte.
Meine Problemumgehung bestand darin, eine Steuerelementvorlage zu verwenden, die alle meine Steuerelemente enthält, die auf einer Registerkarte angezeigt werden sollen. Innerhalb der Vorlage können Sie die Name-Eigenschaft verwenden und Daten aus anderen Steuerelementen an Eigenschaften des benannten Steuerelements binden, zumindest innerhalb derselben Vorlage.
Verwenden Sie als Inhalt des TabItem-Steuerelements ein einfaches Steuerelement und legen Sie die ControlTemplate entsprechend fest:
Wenn Sie über den Code dahinter auf die benannten Steuerelemente in der Vorlage zugreifen, müssen Sie den visuellen Baum verwenden.
quelle