I have a set of controls with attached commands and logic that are constantly reused in the same way. I decided to create a user control that holds all the common controls and logic.
However I also need the control to be able to hold content that can be named. I tried the following:
<UserControl.ContentTemplate> <DataTemplate> <Button>a reused button</Button> <ContentPresenter Content="{TemplateBinding Content}"/> <Button>a reused button</Button> </DataTemplate> </UserControl.ContentTemplate>
However it seems any content placed inside the user control cannot be named. For example if I use the control in the following way:
<lib:UserControl1> <Button Name="buttonName">content</Button> </lib:UserControl1>
I receive the following error:
Cannot set Name attribute value 'buttonName' on element 'Button'. 'Button' is under the scope of element 'UserControl1', which already had a name registered when it was defined in another scope.
If I remove the buttonName, then it compiles, however I need to be able to name the content. How can I achieve this?
User controls, in WPF represented by the UserControl class, is the concept of grouping markup and code into a reusable container, so that the same interface, with the same functionality, can be used in several different places and even across several applications.
A window is managed by the OS and is placed on the desktop. A UserControl is managed by wpf and is placed in a Window or in another UserControl. Applcations could be created by have a single Window and displaying lots of UserControls in that Window.
The XamlFileBrowser Control Create a XAML application using Visual Studio 2008 and add a new item by right clicking on the project, select Add >> New Item from the menu and select User Control from the available templates.
The answer is to not use a UserControl to do it.
Create a class that extends ContentControl
public class MyFunkyControl : ContentControl { public static readonly DependencyProperty HeadingProperty = DependencyProperty.Register("Heading", typeof(string), typeof(MyFunkyControl), new PropertyMetadata(HeadingChanged)); private static void HeadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((MyFunkyControl) d).Heading = e.NewValue as string; } public string Heading { get; set; } }
then use a style to specify the contents
<Style TargetType="control:MyFunkyControl"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="control:MyFunkyControl"> <Grid> <ContentControl Content="{TemplateBinding Content}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
and finally - use it
<control:MyFunkyControl Heading="Some heading!"> <Label Name="WithAName">Some cool content</Label> </control:MyFunkyControl>
It seems this is not possible when XAML is used. Custom controls seem to be a overkill when I actually have all the controls I need, but just need to group them together with a small bit of logic and allow named content.
The solution on JD's blog as mackenir suggests, seems to have the best compromise. A way to extend JD's solution to allow controls to still be defined in XAML could be as follows:
protected override void OnInitialized(EventArgs e) { base.OnInitialized(e); var grid = new Grid(); var content = new ContentPresenter { Content = Content }; var userControl = new UserControlDefinedInXAML(); userControl.aStackPanel.Children.Add(content); grid.Children.Add(userControl); Content = grid; }
In my example above I have created a user control called UserControlDefinedInXAML which is define like any normal user controls using XAML. In my UserControlDefinedInXAML I have a StackPanel called aStackPanel within which I want my named content to appear.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With