How to set the correct border for a datagrid in a datagrid in WPF

If you use a datagrid in the DataGrid.RowDetailsTemplate and set the last column width to * and the datagrid is set to HorizontalAlignment="Stretch", then you might get a horizontal scrollbar. To prevent this, set the HorizontalScrollBarVisibility="Disabled" on the top datagrid and subdatagrids

 

The first screendump show the datagrids with HorizontalScrollBarVisibility set to “Enabled”, as you can see at the bottom of the screendump, the datagrid contains a horizontal scrollbar. This is, because the last column width is set to *.

image

The second screendump shows the correct layout (with HorizontalScrollBarVisibility set to "Disabled")

image

How to stretch the last column to the width of the datagrid in WPF

If you want to let the last column in a datagrid fill the datagrid, you should use the first columns width to auto en set the last column width to * and specify minimum widths for the columns:

<DataGrid Name="subsysteemSettingsDataGrid" AutoGenerateColumns="False" HeadersVisibility="Column" HorizontalAlignment="Stretch" Margin="10" HorizontalGridLinesBrush="LightGray" VerticalGridLinesBrush="LightGray" HorizontalScrollBarVisibility="Disabled" CanUserAddRows="False" BorderBrush="#FF8C8E94" SelectionUnit="FullRow" CellStyle="{StaticResource SelectedSubDataGridCellStyle}"> <DataGrid.Columns> <DataGridTextColumn Header="Name" Binding="{Binding Path=Name, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" MinWidth="150" Width="Auto" /> <DataGridTextColumn Header="Value" Binding="{Binding Path=Value, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" MinWidth="200" Width="*" /> </DataGrid.Columns> </DataGrid>

De screendump below shows the last column stretched to the width of the datagrid

 

image

How to set the style of a specific control in WPF by using a StaticResource

 

If you want to set the style for all “DataGridCells”, create a static resource with TargetType="DataGridCell". If you specify a x:Key for that static resource, you can style the cells in a specific datagrid.

In the image below you can see, that the selected rows in the subdatagrids have a different color then the selected rows in the top datagrids:

 

image

<Window x:Class="Ada.Eac.UI.DeployWindow"
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DeployWindow" Height="300" Width="988" SnapsToDevicePixels="True" UseLayoutRounding="True" WindowState="Maximized" WindowStartupLocation="CenterScreen" Icon="/Eac;component/Dashboard.ico" Loaded="Window_Loaded">
<Window.Resources>
<Style TargetType="DataGridCell" x:Key="SelectedDataGridCellStyle">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0.0" Color="#FFE3F7FF"/>
<GradientStop Offset="1.0" Color="#FFB8E8FB"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="BorderBrush" Value="#FFB8E8FB"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="DataGridCell" x:Key="SelectedSubDataGridCellStyle">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0.0" Color="#FFFFFFFF"/>
<GradientStop Offset="1.0" Color="Red"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="BorderBrush" Value="#FFB8E8FB"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TabControl Grid.Column="1" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10,10,10,10" Name="mainTabControl">
<TabItem Header="Configuration" Name="configurationTabItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"></RowDefinition>
<RowDefinition Height="40"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Button Grid.Column="0" Grid.Row="0" Content="Save" Height="25" Width="125" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5,5,10,10" Name="saveButton" Cursor="Hand" Click="SaveButton_Click" ToolTip="Saves settings to the Configuration.xml" />
<Label Grid.Column="0" Grid.Row="0" Content="Password" Height="28" HorizontalAlignment="Left" Margin="161,5,0,0" Name="passwordLabel" VerticalAlignment="Top" />
<PasswordBox Grid.Column="0" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="228,8,0,0" Name="passwordBox" VerticalAlignment="Top" Width="220" />
<Label Grid.Column="0" Grid.Row="0" Content="PasswordEncrypted" Height="28" HorizontalAlignment="Left" Margin="463,5,0,0" Name="passwordEncryptedLabel" VerticalAlignment="Top" />
<TextBox Grid.Column="0" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="580,8,0,0" Name="passwordEncryptedTextBox" VerticalAlignment="Top" Width="220" />
<Button Grid.Column="0" Grid.Row="0" Content="Encrypt" Height="23" HorizontalAlignment="Left" Margin="820,5,0,0" Name="encryptButton" VerticalAlignment="Top" Width="75" Cursor="Hand" Click="EncryptButton_Click" ToolTip="Encrypts the given password" />
<Button Grid.Column="0" Grid.Row="1" Content="Show advanced UI" Height="25" Width="125" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5,5,10,10" Name="advancedButton" Cursor="Hand" Click="AdvancedButton_Click" ToolTip="Shows a XML editor for editing settings and tasks" />
<Label Grid.Column="0" Grid.Row="1" Content="Find" Height="28" HorizontalAlignment="Left" Margin="188,5,0,0" Name="findLabel" VerticalAlignment="Top" />
<TextBox Grid.Column="0" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="228,8,0,0" Name="findTextBox" VerticalAlignment="Top" Width="220" />
<Label Grid.Column="0" Grid.Row="1" Content="Replace" Height="28" HorizontalAlignment="Left" Margin="520,5,0,0" Name="replaceLabel" VerticalAlignment="Top" />
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="580,8,136,0" Name="replaceTextBox1" VerticalAlignment="Top" Width="220" />
<Button Grid.Column="0" Grid.Row="1" Content="Replace" Height="23" HorizontalAlignment="Left" Margin="820,5,0,0" Name="replaceButton" VerticalAlignment="Top" Width="75" Click="ReplaceButton_Click" Cursor="Hand" ToolTip="Finds a string in the Configuration.xml en replaces it" />
<avalonedit:TextEditor Grid.Column="0" Grid.Row="2"  HorizontalAlignment="Stretch" Name="configurationTextBox" Margin="10,10,10,10" VerticalAlignment="Stretch" VerticalScrollBarVisibility="Auto" ShowLineNumbers="True" Visibility="Hidden" />
<Grid Grid.Column="0" Grid.Row="2" Name="settingsGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="200"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Margin="5,0,0,0" Padding="0" Name="productSettingsLabel" Content="Product settings" />
<DataGrid Grid.Column="0" Grid.Row="1" Name="productSettingsDataGrid" Margin="5,0,0,0" Visibility="Visible" AutoGenerateColumns="False" HeadersVisibility="Column" RowDetailsVisibilityChanged="settingsDataGrid_RowDetailsVisibilityChanged" HorizontalAlignment="Left" HorizontalGridLinesBrush="LightGray"  VerticalGridLinesBrush="LightGray" HorizontalScrollBarVisibility="Disabled" CanUserAddRows="False" BorderBrush="#FF8C8E94" SelectionUnit="FullRow" CellStyle="{StaticResource SelectedDataGridCellStyle}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="200"/>
<DataGridTextColumn Header="Value" Binding="{Binding Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="200" Width="*" />
</DataGrid.Columns>
</DataGrid>
<Label Grid.Column="0" Grid.Row="2" Margin="5,5,0,0" Padding="0" Name="subsystemSettingsLabel" Content="Subsytem settings" />
<DataGrid Grid.Column="0" Grid.Row="3" Name="settingsDataGrid" Margin="5,0,0,0" Visibility="Visible" AutoGenerateColumns="False" HeadersVisibility="Column" RowDetailsVisibilityChanged="settingsDataGrid_RowDetailsVisibilityChanged" HorizontalAlignment="Left" HorizontalGridLinesBrush="LightGray"  VerticalGridLinesBrush="LightGray" HorizontalScrollBarVisibility="Disabled" CanUserAddRows="False" BorderBrush="#FF8C8E94" SelectionUnit="FullRow" CellStyle="{StaticResource SelectedDataGridCellStyle}">
<DataGrid.Columns>
<DataGridTemplateColumn MinWidth="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Margin="2" Name="subsystemDeployButton" Content="Deploy" Click="subsystemDeployButton_Click" Cursor="Hand" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn MinWidth="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Margin="2" Name="subsystemUpdateFilesButton" Content="Update Files" Click="subsystemUpdateFilesButton_Click" Cursor="Hand" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn MinWidth="20" Header="Installed">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Margin="20,7,5,5" Name="installedCheckBox" IsChecked="{Binding Path=Installed, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="False" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="*"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid Name="subsysteemSettingsDataGrid" AutoGenerateColumns="False" HeadersVisibility="Column" HorizontalAlignment="Stretch" Margin="10" HorizontalGridLinesBrush="LightGray" VerticalGridLinesBrush="LightGray" HorizontalScrollBarVisibility="Disabled" CanUserAddRows="False" BorderBrush="#FF8C8E94" SelectionUnit="FullRow"  CellStyle="{StaticResource SelectedSubDataGridCellStyle}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="150" Width="Auto" />
<DataGridTextColumn Header="Value" Binding="{Binding Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="200" Width="*" />
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
</Grid>
</TabItem>
<TabItem Header="Deploy" Name="deployTabItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="60"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Button Content="Prerequisites" Height="30" Width="140" HorizontalAlignment="Left" Margin="10,15,0,15" Name="prerequisitesButton" Cursor="Hand" ToolTip="Saves the settings to the Configuration.xml and then executes all enabled PrerequisitesTasks" Click="prerequisitesButton_Click" />
<Button Content="Deploy" Height="30" Width="140" HorizontalAlignment="Left" Margin="165,15,0,15" Name="deployButton" Cursor="Hand" Click="DeployButton_Click" ToolTip="Saves the settings to the Configuration.xml and then executes all enabled PrerequisitesTasks, DeployTasks, UpdateFilesTasks and EndToEndTests for all enabled subsystems" />
<Button Content="Update Files" Height="30" Width="140" HorizontalAlignment="Left" Margin="319,15,0,15" Name="updateFilesButton" Cursor="Hand" Click="UpdateFilesButton_Click" ToolTip="Saves the settings to the Configuration.xml and then executes all enabled UpdateFilesTasks for all enabled subsystems" />
<Button Content="End to End tests" Height="30" Width="140" HorizontalAlignment="Left" Margin="474,15,0,15" Name="endToEndTestsButton" Cursor="Hand" ToolTip="Saves the settings to the Configuration.xml and then executes all enabled End to End tests" Click="endToEndTestsButton_Click" />
<Button Content="Clear Output" Height="30" Width="140" HorizontalAlignment="Left" Margin="631,15,0,15" Name="clearOutputButton" Cursor="Hand" Click="ClearOutputButton_Click" ToolTip="Clears the output textbox" />
<TextBox Grid.Column="1" Grid.Row="2"  HorizontalAlignment="Stretch" Name="outputTextBox" Margin="10,10,10,10" VerticalAlignment="Stretch" AcceptsReturn="True" VerticalScrollBarVisibility="Auto" />
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>

How to show the output of a *.bat or *.cmd file in a WPF application, without waiting for the *.bat file to end

Notes

  • The functions
    – process.StandardOutput.ReadToEnd();
    – process.StandardOutput.Read();
    – process.StandardOutput.ReadLine();
    will wait for the process to end and then output the result.
  • If you want to show the output during processing, you should use
    – process.OutputDataReceived += new DataReceivedEventHandler(ProcessOuputHandler);
    – and process.BeginOutputReadLine();
  • Because the BeginOutputReadLine will spawn a new thread, you can’t access the UI directly. If you want to update a textbox, you should use the control.Dispatcher.Invoke function.
  • With the control.Dispatcher.CheckAccess() you can determine if the functions is called from the UI thread or not.
  • [myWpfWindow] is a WPF window containing a textbox with the name [outputTextBox] and a button with the name [testButton].
  • The function [ShowingOutputOfBatFile] is called from a [testButton] click eventhandler

 

Code

 

public void ShowingOutputOfBatFile()
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = @"C:\Temp\Test.bat";
startInfo.Arguments = "firstParameter secondParamter";
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
startInfo.WorkingDirectory = @"C:\Temp";
// Use startInfo.CreateNoWindow = HideWindow; if you want to hide the window
using (Process process = new Process())
{
process.StartInfo = startInfo;
process.OutputDataReceived += new DataReceivedEventHandler(ProcessOuputHandler);
process.Start();
process.BeginOutputReadLine();
while (!process.HasExited)
{
// Refresh you're WPF window here
myWpfWindow.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
Thread.Sleep(1000);
}
}
}
public void ProcessOuputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
if (!String.IsNullOrEmpty(outLine.Data))
{
if (!outputTextBox.Dispatcher.CheckAccess())
{
// Called from a none ui thread, so use dispatcher
ShowLoggingDelegate showLoggingDelegate = new ShowLoggingDelegate(ShowLogging);
outputTextBox.Dispatcher.Invoke(DispatcherPriority.Normal, showLoggingDelegate, outLine.Data);
}
else
{
// Called from UI trhead so just update the textbox
ShowLogging(outLine.Data);
};
}
}
private delegate void ShowLoggingDelegate(string text);
private static Action EmptyDelegate = delegate() { };
/// <summary>
/// Show the logging on screen
/// </summary>
/// <param name="text"></param>
private void ShowLogging(string text)
{
myWpfWindow.outputTextBox.AppendText(text);
myWpfWindow.outputTextBox.ScrollToEnd();
}

Setting 100% width and 100% height for a Textbox in WPF

If you want to stretch a textbox to the width of the window in WPF you can use the following code

 

Code

<Window x:Class="Ada.Eac.UI.DeployWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DeployWindow" Height="300" Width="988" SnapsToDevicePixels="True" UseLayoutRounding="True" WindowState="Maximized" WindowStartupLocation="CenterScreen" Icon="/Eac;component/Dashboard.ico">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="60"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Button Grid.Column="1" Content="Deploy" Height="30" Width="100" HorizontalAlignment="Left" Margin="10,10,10,10" Name="deployButton" Cursor="Hand" />
<TextBox Grid.Column="1" Grid.Row="2"  HorizontalAlignment="Stretch" Name="outputTextBox" Margin="10,10,10,10" VerticalAlignment="Stretch" AcceptsReturn="True" VerticalScrollBarVisibility="Auto" />
</Grid>
</Window>

 

 

Screendump

image

Center a group box in a WPF application

If you want to center a group box in a WPF application, you can use the HorizontalAlignment property.

HorizontalAlignment="Center"

Make sure the margin left and margin right are 0

 

Margin="0,30,0,0"

image

 

Code

<Window x:Class="Rvl.DashBoard.Wpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Dashboard" Height="350" Width="525" WindowState="Maximized" Icon="/Rvl.DashBoard.Wpf;component/Dashboard.ico">
<Grid>
<GroupBox Header="Continuous Deployment" Height="107" HorizontalAlignment="Center" Name="continuousDeploymentGroupBox" VerticalAlignment="Top" Width="322" HorizontalContentAlignment="Center" Margin="0,30,0,0">
<Grid>
<Button Content="AKS" Height="23" HorizontalAlignment="Left" Margin="29,20,0,0" Name="aksButton" VerticalAlignment="Top" Width="75" Click="Deploy_AKS" Cursor="Hand" />
<Button Content="LocatiePlatform" Height="23" HorizontalAlignment="Left" Margin="165,20,0,0" Name="locatiePlatformButton" VerticalAlignment="Top" Width="109" Click="Deploy_LocatiePlatform" Cursor="Hand" />
</Grid>
</GroupBox>
</Grid>
</Window>

Showing bmp, png, jpg or gif images as buttons in WPF in the best quality

If you want to show a bmp, png, jpg or gif image as a button in WPF in the best quality, you can use the following XAML:

 

XAML

<Button  HorizontalAlignment="Left" Margin="312,45,0,0" Name="refreshButton" VerticalAlignment="Top" Width="60" Height="45" Cursor="Hand" Click="button1_Click">
<Image Source="/Ada.Tip.WpfUserControls;component/Images/SmallSync.png" Stretch="None" />
</Button>

 

* The Stretch property of the Image is set to “None”, so the image is shown in it’s original dimensions. If you let WPF scale the image you might not get the best quality. I use Paint .NET to scale the image to the correct size and then show the image in it’s original dimensions in WPF.

* Ada.Tip.WpfUserControls is the name of my Visual Studio 2010 project and assembly name.

 

Add you’re image to the project and it will automatically be converted to a resource entry in you’re assembly

 

image

 

Result (Refresh button)

image