Click here to Skip to main content
15,937,127 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi everyone, I am trying to create a CustomUser control, because I need a base template for all userControls in my App (I'm trying to make a Single-Window-Application) with a sort of Window-in-Window, where the userControls are sort of windows in the MainWindow.xaml.

To make it I tried to create my usercontrol in XAML and CS code, with the following template:
XML
<UserControl.Template>
    <ControlTemplate>
        <Grid >
            <Border Name="border" BorderBrush="Gray" removed="WhiteSmoke" BorderThickness="3" CornerRadius="20,0,40,0" >
                <Border.Effect>
                    <DropShadowEffect Color="Black" ShadowDepth="7.5" Direction="315" />
                </Border.Effect>
            </Border>
            <Border Name="background" Margin="{Binding BorderThickness, ElementName=border}" CornerRadius="20,0,40,0" removed="WhiteSmoke" />

            <Grid >
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Grid VerticalAlignment="Top" Margin="{Binding BorderThickness, ElementName=border}" Height="20">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition />
                        <ColumnDefinition Width="35"/>
                        <ColumnDefinition Width="35"/>
                        <ColumnDefinition Width="35"/>
                    </Grid.ColumnDefinitions>

                    <TextBlock Margin="10,1" FontWeight="Bold" FontStyle="Italic" VerticalAlignment="Center" Text="{Binding Title, ElementName=userControl}" />
                    <Button Grid.Column="3" Margin="1" VerticalContentAlignment="Center" FontWeight="ExtraBold" FontFamily="Arial Black" Foreground="Red" Content="?" Click="close_Click" ToolTip="Close" />
                    <Button Grid.Column="2" Margin="1" VerticalContentAlignment="Center" FontWeight="ExtraBold" FontFamily="Arial Black" Content="?" Click="maximize_Click" ToolTip="Maximize" />
                    <Button Grid.Column="1" Margin="1" VerticalContentAlignment="Center" FontWeight="ExtraBold" FontFamily="Arial Black" Content="_" Click="minimize_Click" ToolTip="Minimize" />
                </Grid>

                <ContentControl Content="{Binding Content, ElementName=userControl}" Margin="5" Grid.Row="1" />
            </Grid>
        </Grid>
    </ControlTemplate>
</UserControl.Template>


the problem is that WPF doesn't allow to use XAML-based control as roots (I create a UserControl but I replace root 'UserControl' with c:MyUserControl), so I need to convert it into Code-based control.

Can you please help me? Because I tryied, but the problem is setting events and RowDefinitions.

Thanks for your kind help and sorry for my bad English.
Posted

Something seems off about your code, here is what a template looks like for a project I'm working on:

XML
    <style targettype="{x:Type local:TestBlockControl}">
        <setter property="Template">
            <setter.value>
                <controltemplate targettype="{x:Type local:TestBlockControl}">
                    <grid cliptobounds="False">
</grid></controltemplate></setter.value></setter></style>


As you see, I'm setting the default style for a user control named TestBlockControl. It should work the same for any derived type controls but you should not target UserControl for your template since it will try to apply that template to all user controls. That may sound like what you want, but trust me, its not. You will want to target your MyUserControl type.

Your code should look something more like:

XML
<style targettype="{x:Type local:MyUserControl}">
    <setter property="Template">
        <setter.value>
            <controltemplate targettype="{x:Type local:MyUserControl}">
            <grid>
                <border name="border" borderbrush="Gray" removed="WhiteSmoke" borderthickness="3" cornerradius="20,0,40,0">
                    <border.effect>
                        <dropshadoweffect color="Black" shadowdepth="7.5" direction="315" />
                    </border.effect>
                </border>
                <border name="background" margin="{Binding BorderThickness, ElementName=border}" cornerradius="20,0,40,0" removed="WhiteSmoke" />
 
                <grid>
                    <grid.rowdefinitions>
                        <rowdefinition height="Auto" />
                        <rowdefinition />
                    </grid.rowdefinitions>
                    <grid verticalalignment="Top" margin="{Binding BorderThickness, ElementName=border}" height="20">
                        <grid.columndefinitions>
                            <columndefinition />
                            <columndefinition width="35" />
                            <columndefinition width="35" />
                            <columndefinition width="35" />
                        </grid.columndefinitions>
 
                        <textblock margin="10,1" fontweight="Bold" fontstyle="Italic" verticalalignment="Center" text="{Binding Title, ElementName=userControl}" />
                        <Button Grid.Column="3" Margin="1" VerticalContentAlignment="Center" FontWeight="ExtraBold" FontFamily="Arial Black" Foreground="Red" Content="?" Click="close_Click" ToolTip="Close" />
                        <Button Grid.Column="2" Margin="1" VerticalContentAlignment="Center" FontWeight="ExtraBold" FontFamily="Arial Black" Content="?" Click="maximize_Click" ToolTip="Maximize" />
                        <Button Grid.Column="1" Margin="1" VerticalContentAlignment="Center" FontWeight="ExtraBold" FontFamily="Arial Black" Content="_" Click="minimize_Click" ToolTip="Minimize" />
                    </grid>
 
                    <contentcontrol content="{Binding Content, ElementName=userControl}" margin="5" grid.row="1" />
                </grid>
            </grid>
            </controltemplate>
        </setter.value>
    </setter>
</style>


This style goes in your Themes/Generic.xaml file or you need to reference it in that file by using the MergedDictionaries key at the top.
 
Share this answer
 
Comments
Ron Beyer 24-Jan-14 15:37pm    
Please note there is a bug in the CodeProject box that when submitting XML/XAML it removes all capitalization. I reported this bug.
Cuccurullo.Alex 24-Jan-14 15:52pm    
I tried to do what you wrote but it doesn't work..
I setted the Generic.xaml with the code but it seems my control doesn't get it..
Ron Beyer 24-Jan-14 15:54pm    
Do you have something like this in the static constructor on your control?

DefaultStyleKeyProperty.OverrideMetadata(typeof(MyUserControl), new FrameworkPropertyMetadata(typeof(MyUserControl)));

?
Cuccurullo.Alex 24-Jan-14 16:01pm    
Yes I tried with the same result
Cuccurullo.Alex 24-Jan-14 16:08pm    
May it be possible to set it in c# code?
I solved this on my own by creating the template in the constructor of my control.. It was not easy but I did it..
Here the code I wrote.

C#
this.DataContext = this;

            var template = new ControlTemplate();

            var mainGrid = new FrameworkElementFactory(typeof(Grid));

            var borderTemplate = new FrameworkElementFactory(typeof(Border));
            borderTemplate.SetValue(Border.BorderBrushProperty, Brushes.Gray);
            borderTemplate.SetValue(Border.BorderThicknessProperty, new Thickness(3));
            borderTemplate.SetValue(Border.BackgroundProperty, Brushes.WhiteSmoke);
            borderTemplate.SetBinding(Border.CornerRadiusProperty, new Binding("CornerRadius"));
            borderTemplate.SetValue(Border.EffectProperty, new DropShadowEffect() { Color = Colors.Black, ShadowDepth = 7.5, Direction = 315 });

            var gridTemplate = new FrameworkElementFactory(typeof(Grid));
            gridTemplate.SetValue(Grid.MarginProperty, new Thickness(3));

            var titleColTemplate = new FrameworkElementFactory(typeof(ColumnDefinition));

            var minimizeColTemplate = new FrameworkElementFactory(typeof(ColumnDefinition));
            minimizeColTemplate.SetValue(ColumnDefinition.WidthProperty, new GridLength(35));

            var maximizeColTemplate = new FrameworkElementFactory(typeof(ColumnDefinition));
            maximizeColTemplate.SetValue(ColumnDefinition.WidthProperty, new GridLength(35));

            var closeColTemplate = new FrameworkElementFactory(typeof(ColumnDefinition));
            closeColTemplate.SetValue(ColumnDefinition.WidthProperty, new GridLength(35));

            var titleRowTemplate = new FrameworkElementFactory(typeof(RowDefinition));
            titleRowTemplate.SetValue(RowDefinition.HeightProperty, new GridLength(20));

            var contentRowTemplate = new FrameworkElementFactory(typeof(RowDefinition));

            var titleTemplate = new FrameworkElementFactory(typeof(TextBlock));
            titleTemplate.SetValue(TextBlock.VerticalAlignmentProperty, VerticalAlignment.Center);
            titleTemplate.SetValue(TextBlock.FontWeightProperty, FontWeights.Bold);
            titleTemplate.SetValue(TextBlock.FontStyleProperty, FontStyles.Italic);
            titleTemplate.SetBinding(TextBlock.TextProperty, new Binding("Title"));
            titleTemplate.SetValue(TextBlock.MarginProperty, new Thickness(10, 0, 0, 0));

            var minimizeTemplate = new FrameworkElementFactory(typeof(Button));
            minimizeTemplate.SetValue(Button.MarginProperty, new Thickness(1));
            minimizeTemplate.SetValue(Button.FontWeightProperty, FontWeights.ExtraBold);
            minimizeTemplate.SetValue(Button.FontFamilyProperty, new FontFamily("Arial Black"));
            minimizeTemplate.SetValue(Grid.ColumnProperty, 1);
            minimizeTemplate.SetValue(Button.ContentProperty, "_");
            minimizeTemplate.AddHandler(Button.ClickEvent, new RoutedEventHandler(this.minimize_Click));

            var maximizeTemplate = new FrameworkElementFactory(typeof(Button));
            maximizeTemplate.SetValue(Button.MarginProperty, new Thickness(1));
            maximizeTemplate.SetValue(Button.FontWeightProperty, FontWeights.ExtraBold);
            maximizeTemplate.SetValue(Button.FontFamilyProperty, new FontFamily("Arial Black"));
            maximizeTemplate.SetValue(Grid.ColumnProperty, 2);
            maximizeTemplate.SetValue(Button.ContentProperty, "☐");
            maximizeTemplate.AddHandler(Button.ClickEvent, new RoutedEventHandler(this.maximize_Click));

            var closeTemplate = new FrameworkElementFactory(typeof(Button));
            closeTemplate.SetValue(Button.MarginProperty, new Thickness(1));
            closeTemplate.SetValue(Button.FontWeightProperty, FontWeights.ExtraBold);
            closeTemplate.SetValue(Button.FontFamilyProperty, new FontFamily("Arial Black"));
            closeTemplate.SetValue(Grid.ColumnProperty, 3);
            closeTemplate.SetValue(Button.ContentProperty, "✘");
            closeTemplate.SetValue(Button.ForegroundProperty, Brushes.Red);
            closeTemplate.AddHandler(Button.ClickEvent, new RoutedEventHandler(this.close_Click));

            var contentTemplate = new FrameworkElementFactory(typeof(ContentControl));
            contentTemplate.SetValue(Grid.RowProperty, 1);
            contentTemplate.SetValue(Grid.ColumnSpanProperty, 4);
            contentTemplate.SetValue(ContentControl.MarginProperty, new Thickness(5));
            contentTemplate.SetBinding(ContentControl.ContentProperty, new Binding("Content"));

            gridTemplate.AppendChild(titleColTemplate);
            gridTemplate.AppendChild(minimizeColTemplate);
            gridTemplate.AppendChild(maximizeColTemplate);
            gridTemplate.AppendChild(closeColTemplate);
            gridTemplate.AppendChild(titleRowTemplate);
            gridTemplate.AppendChild(contentRowTemplate);
            gridTemplate.AppendChild(titleTemplate);
            gridTemplate.AppendChild(minimizeTemplate);
            gridTemplate.AppendChild(maximizeTemplate);
            gridTemplate.AppendChild(closeTemplate);
            gridTemplate.AppendChild(contentTemplate);

            mainGrid.AppendChild(borderTemplate);
            mainGrid.AppendChild(gridTemplate);

            template.VisualTree = mainGrid;

            this.Template = template;


Thank Ron Beyer for your kind help :)
 
Share this answer
 
Comments
Ron Beyer 24-Jan-14 17:29pm    
Glad you got it solved!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900