Initializing controls within your WPF custom control template

Sometimes your custom control is a composite control where your template contains multiple WPF controls.
If you want to initialize those controls from code this cannot be done in the constructor of your custom control.
To do so, there is an override of the OnApplyTemplate method which is the best place to do Initialization.

Example:

public override void OnApplyTemplate() { Button myButton = this.Template.FindName("MyButton", this) as Button; myButton.Click +=new RoutedEventHandler(myButton_Click); myButton.Content = "Initialized"; }

WPF pivoted table (vertical columns)

Source code: download

I struggled some time to find a way to create a pivoted table where the columns are shown vertical instead of horizontal.
This is a dynamic table where databinding is used to retrieve the data and by clicking the columns they also needed to be sorted.
Sorting is not included in this sample, but this is easily accomplished by adding a command to the columns (buttons).
With some googling I came accross the dependency property named "SharedSizeGroup" and that did the trick.

image 

First you create your DataTemplate with the rowdefinitions where every row has its own SharedSizeGroup.
Then you define the controltemplate for the listbox that is databound to the data.
This template also contains the same amount of rows and all rows that need to line up share the same SharedSizeGroup as defined in the DataTemplate.
If someone has a better solution, I am eager to learn!! Drop me a line.

<Window x:Class="VerticalGridColumns.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:data="clr-namespace:VerticalGridColumns" Title="Pivoted Grid" Height="300" Width="300"> <Window.Resources> <ObjectDataProvider x:Key="PersonsProvider" ObjectType="{x:Type data:Persons}" /> <ControlTemplate x:Key="HeaderButtonTemplate" TargetType="{x:Type Button}"> <Border Width="auto" Height="auto" BorderThickness="1" BorderBrush="Gray" Padding="10,3,10,3" Background="Gainsboro"> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="True"/> </Border> </ControlTemplate> <DataTemplate x:Key="MyDataTemplate"> <Border BorderThickness="1" BorderBrush="Gray"> <Grid ShowGridLines="True"> <Grid.RowDefinitions> <RowDefinition Height="auto" SharedSizeGroup="NameRow" /> <RowDefinition Height="auto" SharedSizeGroup="AgeRow" /> <RowDefinition Height="auto" SharedSizeGroup="GenderRow" /> </Grid.RowDefinitions> <TextBlock Grid.Row="0" VerticalAlignment="Center" Padding="3,0,3,0" Text="{Binding Path=Name}" /> <TextBlock Grid.Row="1" VerticalAlignment="Center" Padding="3,0,3,0" Text="{Binding Path=Age}" /> <TextBlock Grid.Row="2" VerticalAlignment="Center" Padding="3,0,3,0" Text="{Binding Path=Gender}" /> </Grid> </Border> </DataTemplate> <ControlTemplate x:Key="MyListBoxTemplate"> <Grid Grid.IsSharedSizeScope="True"> <DockPanel> <Border BorderThickness="1"> <Grid DockPanel.Dock="Left"> <Grid.RowDefinitions> <RowDefinition Height="auto" SharedSizeGroup="NameRow" /> <RowDefinition Height="auto" SharedSizeGroup="AgeRow" /> <RowDefinition Height="auto" SharedSizeGroup="GenderRow" /> </Grid.RowDefinitions> <Button Template="{StaticResource HeaderButtonTemplate}" Grid.Row="0">Name</Button> <Button Template="{StaticResource HeaderButtonTemplate}" Grid.Row="1" Content="Age" /> <Button Template="{StaticResource HeaderButtonTemplate}" Grid.Row="2" Content="Gender"/> </Grid> </Border> <VirtualizingStackPanel IsItemsHost="True" Orientation="Horizontal" /> </DockPanel> </Grid> </ControlTemplate> </Window.Resources> <Grid> <StackPanel Margin="10,10,10,10"> <TextBlock Text="This is an example of a pivoted grid" Margin="0,10, 0, 10" /> <ListBox x:Name="MyListBox" Height="auto" ItemTemplate="{StaticResource MyDataTemplate}" Template="{StaticResource MyListBoxTemplate}" ItemsSource="{Binding Source={StaticResource PersonsProvider}}" VerticalAlignment="Top" /> </StackPanel> </Grid> </Window>

WPF implementation of a basic Accordion control

Source: WPF Accordion Control Source

WPF does not contain an out of the box accordion control, but it does provide an expander control.
Since an accordion control is nothing more than a stack of expanders it is very easy to build one ourselves.
This shows just a basic control, Feel free to pimp the control with a custom template or extend it with your functionality.

image_thumb

First create a WPF Custom control library.
Then add a "Custom Control (WPF)" item to the project and name it "Accordion.cs"
Add the following code into this file:

Note: As you can see, the Accordion control is just a custom stackpanel with functionality to expand/collapse the expanders within the stackpanel.

namespace WpfDemoControlLibrary { public class Accordion : StackPanel { static Accordion() { DefaultStyleKeyProperty.OverrideMetadata(typeof(Accordion), new FrameworkPropertyMetadata(typeof(Accordion))); } protected override void OnInitialized(EventArgs e) { base.OnInitialized(e); this.InitializeAccordion(); } protected void InitializeAccordion() { Expander selectedExpander; foreach (UIElement element in this.Children) { selectedExpander = element as Expander; if (selectedExpander != null) { selectedExpander.Expanded += new RoutedEventHandler(selectedExpander_Expanded); } } } void selectedExpander_Expanded(object sender, RoutedEventArgs e) { Expander selectedExpander = sender as Expander; Expander otherExpander = null; ContentPresenter contentPresenter = null; double totalExpanderHeight = 0; if (selectedExpander != null) { foreach (UIElement element in this.Children) { otherExpander = element as Expander; if (otherExpander != null & otherExpander != selectedExpander) { if (otherExpander.IsExpanded) { contentPresenter = otherExpander.Template.FindName("ExpandSite", otherExpander) as ContentPresenter; if(contentPresenter != null) totalExpanderHeight -= contentPresenter.ActualHeight; } otherExpander.IsExpanded = false; totalExpanderHeight += otherExpander.ActualHeight; } } if (selectedExpander.IsExpanded) { contentPresenter = selectedExpander.Template.FindName("ExpandSite", selectedExpander) as ContentPresenter; if(contentPresenter != null) contentPresenter.Height = this.ActualHeight - totalExpanderHeight - selectedExpander.ActualHeight; } } } } }

When the prior file was created it added a section to the Theme\General.xaml file.
Make sure it reflects the following line:
<Style TargetType="{x:Type local:Accordion}"></Style>

By adding the following line to the "Properties\AssemblyInfo.cs" file, the control can later be referenced by your personal namespace.

[assembly: XmlnsDefinition("http://schemas.rooijakkers.net/presentation", "WpfDemoControlLibrary")]

Now, Create a test WPF application that references the created control library.
Note: Make sure that you add the previously defined namespace to the top of the window.

image_thumb[5]

That's it.

WPF Client to read the architecture journal!

There is a Architecture Journal Reader available now so you can view and search the issues without having to download it.
Yes, it also allows to search in previous issues ;)

You can download it here

For a screenshot go here

Concatenate Column results into a single string in SQL Server 2005

I wanted to post some samples how you can accomplish column result concatenation into one string with sql server 2005.
If you know another way, let me know.

The following results are from the Categories table of the Northwind database.

image

image


Sample 1:

DECLARE @categories AS VARCHAR(1024) SELECT @categories = CASE IsNull(@categories,'') WHEN '' THEN CategoryName ELSE @categories + '; ' + CategoryName END FROM Categories ORDER BY CategoryName SELECT @categories


Sample 2:
DECLARE @categories AS VARCHAR(1024) SELECT @categories = COALESCE(@categories + '; ', '') + CategoryName FROM Categories ORDER BY CategoryName SELECT @categories AS CategoryNames


Sample 3:
DECLARE @categories AS VARCHAR(1024) SELECT @categories = CAST ( (SELECT CategoryName + '; ' AS [text()] FROM Categories FOR XML PATH('')) AS VARCHAR(1024)) SELECT @categories


Sample 4:
DECLARE @categories AS VARCHAR(1024) SELECT @categories = CAST ( (SELECT CategoryName AS CAT FROM Categories FOR XML RAW, ELEMENTS, TYPE).query ( 'for $CAT in (row/CAT) order by $CAT ascending return concat($CAT, "; ")' )AS VARCHAR(1024) ) SELECT @categories

MySQL Blog Provider for Blogengine.NET 1.2

Due to lack of time I wasn't able to update my mySql provider, but fortunatly there are other initiatives.
There is an expansion pack available at: http://www.codeplex.com/blog
This expansion pack also contains a mySQL Blog Provider.
I've switched back to the default xml provider until there is an integrated mySql provider.

MySQL Blog Provider for Blogengine.NET 1.1

See my post on BlogEngine.Net 1.2 here