I'm using a ListBox, the item template is a grid with two columns. each column needs to take up half of the available space.
If the text within one of these columns gets too big then I need it to wrap.
I'm using the following code:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderBrush="HotPink" BorderThickness="2">
<TextBlock Text="{Binding Title}"
FontFamily="Arial"
FontSize="16"/>
</Border>
<Border Grid.Column="1" BorderBrush="HotPink" BorderThickness="2">
<TextBlock Text="{Binding Description}"
FontFamily="Arial"
FontSize="16"
TextWrapping="Wrap"/>
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
This works fine when the text isn't long. If the text is too long then the second column starts taking up as much space as possible and then overflows off the screen.
I've used the Hot Pink borders to show the outline of each column in the following image.
Is there anyway to get text wrapping to work in this way?
This is not possible. You will have to implement your own panel which ensures the available space is always evenly distributed between the controls using the Measure and Arrange override methods.
Related
Is it possible in XAML to automatically separate elements in a StackPanel no matter what the size of the window is?
In CSS with the property : space between you can send elements to both sides of the parent. This is what I want to reproduce. Is it possible ?
A StackPanel does not work this way , see the documentation. It does not have a notion of the available space or remaining space to divide, it just stacks elements in one direction.
Arranges child elements into a single line that can be oriented horizontally or vertically.
What you can do instead is use a DockPanel. It allows stacking controls to either side of the panel and by default the last element added to it fills the remaining space. The Border here serves as a dummy element to take the remaining space. Usually, you would put a control there that is actually used. Please be aware that this example only reproduces what you explicitly asked for, the panel allows for much more complex layouts. See remarks from the documentation.
<DockPanel>
<Rectangle DockPanel.Dock="Left" Fill="Black" Width="100" Height="100"/>
<Rectangle DockPanel.Dock="Right" Fill="Black" Width="100" Height="100"/>
<Border/>
</DockPanel>
An alternative is to use a Grid with three columns, where the left and right columns use Auto as Width so the contained controls only take up as much space as they need, while the center column has its Width set to *, which will make it fit the remaining space.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Fill="Black" Width="100" Height="100"/>
<Rectangle Grid.Column="2" Fill="Black" Width="100" Height="100"/>
</Grid>
The relevant portion on size attributes for Grid:
Columns and rows that are defined within a Grid can take advantage of Star sizing to distribute remaining space proportionally. When Star is selected as the height or width of a row or column, that column or row receives a weighted proportion of the remaining available space. This is in contrast to Auto, which distributes space evenly based on the size of the content that is within a column or row.
Update for your list example. You can define a data template for the items.
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" Margin="25,60,25,25" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Border Padding="0,25" BorderThickness="0 0 0 1" BorderBrush="#3D3C44">
<Grid Width="378" Background="black">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="hello" Foreground="white"/>
<Border Grid.Column="1" x:Name="PlaceholderForYourContentAndBindings" Background="Red"/>
<theme:OnOff Grid.Column="2" Height="21" Width="38" HorizontalAlignment="Right" Grid.Column="1" Toggle="{Binding status , Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MouseLeftButtonDown="OnOff_MouseLeftButtonDown" />
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
If you want two fixed columns in the ListView, use a UniformGrid instead of a WrapPanel and remove the fixed sizes. With an ItemContainerStyle the items will then scale with the window.
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding StringItems}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="2" Margin="25,60,25,25" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Border Padding="0,25" BorderThickness="0 0 0 1" BorderBrush="#3D3C44">
<Grid Background="black">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="hello" Foreground="white"/>
<Border Grid.Column="1" x:Name="PlaceholderForYourContentAndBindings" Background="Red"/>
<theme:OnOff Grid.Column="2" Height="21" Width="38" HorizontalAlignment="Right" Grid.Column="1" Toggle="{Binding status , Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MouseLeftButtonDown="OnOff_MouseLeftButtonDown" />
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Hi i created lable's and text boxs in wpf but text boxes are started different position How can I make align all the textboxes align in same vertical position?
<DockPanel LastChildFill="True"
HorizontalAlignment="Stretch">
<Label DockPanel.Dock="Left"
Style="{DynamicResource EditorHLabelNoIdentStyle}" Content="{x:Static r:Resources.LABEL_POSITION}"/>
<TextBox ToolTip="{x:Static r:Resources.LABEL_POSITION_TIP}"
Style="{DynamicResource EditorTextBoxStyle}" Text="{Binding XPath=nameofthedataset, Mode=TwoWay}"/>
</DockPanel>
<DockPanel LastChildFill="True"
HorizontalAlignment="Stretch">
<Label DockPanel.Dock="Left"
Style="{DynamicResource EditorHLabelNoIdentStyle}" Content="{x:Static r:Resources.LABEL_POSITION}"/>
<TextBox ToolTip="{x:Static r:Resources.LABEL_POSITION_TIP}"
Style="{DynamicResource EditorTextBoxStyle}" Text="{Binding XPath=keywords, Mode=TwoWay}"/>
</DockPanel>
Use a Grid with two ColumnDefinitions and a RowDefinition for each row and then set the Grid.Row and Grid.Column attached properties
of each element to specify its position in the Grid:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label DockPanel.Dock="Left" Style="{DynamicResource EditorHLabelNoIdentStyle}" Content="{x:Static r:Resources.LABEL_POSITION}"/>
<TextBox Grid.Column="1" ToolTip="{x:Static r:Resources.LABEL_POSITION_TIP}" Style="{DynamicResource EditorTextBoxStyle}"
Text="{Binding XPath=nameofthedataset, Mode=TwoWay}"/>
<Label Grid.Row="1" DockPanel.Dock="Left" Style="{DynamicResource EditorHLabelNoIdentStyle}" Content="{x:Static r:Resources.LABEL_POSITION}"/>
<TextBox Grid.Row="1" Grid.Column="1" ToolTip="{x:Static r:Resources.LABEL_POSITION_TIP}"
Style="{DynamicResource EditorTextBoxStyle}" Text="{Binding XPath=keywords, Mode=TwoWay}"/>
</Grid>
With a number of rows, setting labels or texblocks and textboxes to row and column quickly gets a bit tedious.
You could instead use standard template to line things up in a stackpanel.
A headeredcontentcontrol has a template with a stackpanel to put a header above it's content. This xaml re-templates to use a grid with two columns. The size of the first is shared across the scope of it's containing stackpanel.
You can also avoid repeating all your standard styling and whatnot by applying it in the template.
My markup uses simplified example controls for clarity.
Your textboxes ( or whichever control you wanted to label ) complete with binding, tooltip etc go in the content of a headeredcontentcontrol. The label gets it's value from the header property.
The shared size scope and auto size on the column means all the instances end up with the maximum necessary width a label in that stackpanel requests. So the right column of controls (textboxes) lines up.
<StackPanel Grid.IsSharedSizeScope="True">
<StackPanel.Resources>
<Style TargetType="HeaderedContentControl">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="HeaderedContentControl">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="L" Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="{TemplateBinding Header}"
Margin="2,2,4,2"
/>
<ContentControl Content="{TemplateBinding Content}"
Grid.Column="1"
/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
<HeaderedContentControl Header="Label 1:">
<TextBox Text="Some textbox"/>
</HeaderedContentControl>
<HeaderedContentControl Header="A much longer label:">
<TextBox Text="A second textbox"/>
</HeaderedContentControl>
</StackPanel>
I am attempting to create an onscreen keyboard using a Grid for key layout. Each key consists of a Border with a TextBlock containing a letter. To make the letters scale I have wrapped each TextBlock in a ViewBox, for example;
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="0">
<Border BorderThickness="1" BorderBrush="Gray">
<Viewbox>
<TextBlock Text="a" />
</Viewbox>
</Border>
</Grid>
<Grid Grid.Row="0" Grid.Column="1">
<Border BorderThickness="1" BorderBrush="Gray">
<Viewbox>
<TextBlock Text="b" />
</Viewbox>
</Border>
</Grid>
<Grid Grid.Row="0" Grid.Column="2">
<Border BorderThickness="1" BorderBrush="Gray">
<Viewbox>
<TextBlock Text="c" />
</Viewbox>
</Border>
</Grid>
</Grid>
The problem is when you shrink the control by resizing the window horizontally (i.e. squash the borders together horizontally). As each letter has a slightly different width and height, the amount of zooming/scaling applied by each viewbox is not exactly the same. This results in the letters being rendered at different vertical heights, i.e. the "b" will be on a horizontal plane above the "a" and "c", which looks a little wrong.
The only work around I can think of (which works) relies on fixing the widths of each textblock, e.g. setting Width="10". This, however, feels unsatisfactory as it requires knowledge of the font which will be used to display each letter and an assumption about the maximum width. A middle ground would be to achieve this automatically the largest possible letter/glyph in each viewbox by including a hidden letter in each textblock;
<Grid Grid.Row="0" Grid.Column="0">
<Border BorderThickness="1" BorderBrush="Gray">
<Viewbox>
<Grid>
<TextBlock Text="a" />
<TextBlock Text="X" Visibility="Hidden" />
</Grid>
</Viewbox>
</Border>
</Grid>
I don't like that solution though and would love a reliable way to ensure all textblocks are the same size and so scale acceptably, without hard coding values or assumptions about the font.
Any ideas?
Thanks.
Using a uniform grid and binding to a primary textblock you get a pretty decent scaling:
<UniformGrid Rows="3" Columns="10">
<Viewbox>
<Border>
<TextBlock TextAlignment="Center"
Width="{Binding ActualWidth, ElementName=textBlock, Mode=OneWay}"
Height="{Binding ActualHeight, ElementName=textBlock, Mode=OneWay}">
Q
</TextBlock>
</Border>
</Viewbox>
<Viewbox>
<Border>
<TextBlock x:Name="textBlock" TextAlignment="Center">
W
</TextBlock>
</Border>
</Viewbox>
<Viewbox>
<Border>
<TextBlock Width="{Binding ActualWidth, ElementName=textBlock, Mode=OneWay}"
Height="{Binding ActualHeight, ElementName=textBlock, Mode=OneWay}"
TextAlignment="Center">
E
</TextBlock>
</Border>
</Viewbox>
<Viewbox>
<Border>
<TextBlock Width="{Binding ActualWidth, ElementName=textBlock, Mode=OneWay}"
Height="{Binding ActualHeight, ElementName=textBlock, Mode=OneWay}"
TextAlignment="Center">
R
</TextBlock>
</Border>
</Viewbox>
</UniformGrid>
You'll see each control is bound to the W key - assuming that is the biggest. If you are unsure, you can add a different element as hidden and bind to that - as you implied in your question. The important thing is that the grid sets the size of the main control element.
This MSDN question is answered correctly; http://social.msdn.microsoft.com/Forums/vstudio/en-US/c052fa89-4788-4d85-b266-fdd5c637a0ff/sharing-viewbox-zoom-level-between-items?forum=wpf
The solution relies on leveraging the SharedSizeGroup behaviour on a grid to ensure that the viewbox of every key is the same size as every other viewbox, like so;
<Viewbox>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="col"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition SharedSizeGroup="row"/>
</Grid.RowDefinitions>
<TextBlock Text="a" />
</Grid>
</Viewbox>
Other solutions involving hard coding the width/height of the viewbox, or binding to a common viewbox and filling it with the largest possible glyph work, but are not perfect solutions. The above solution makes no assumptions and relies on built in WPF measure/arrange logic to produce the desired outcome.
I have Grid inside ListPicker full mode item. Grid has two columns. First column should be left-aligned and second right-aligned.
Unfortunately this template doesn't work as expected:
<DataTemplate x:Name="ListFullModeItemTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Name}" />
<TextBlock Grid.Column="1" Text="{Binding Description}" HorizontalAlignment="Right" />
</Grid>
</DataTemplate>
Second TextBlock doesn't align to right.
When I set Grid Width property to specific value i.e.
<Grid Width="700">
...
</Grid>
then it works, but I can't do it because user can rotate phone to Portrait/Landscape.
Any ideas?
EDIT:
I also had the same problem in ListBox.
I fixed it by adding:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
I can't use this in ListPicker because it doesn't have ItemContainerStyle element.
set your grid 's width.
and change it by +=:
OrientationChanged += new EventHandler(SecondPage_OrientationChanged);
try adding TextAlignment="Right"
I am having some difficulty figuring out how to template the following TreeView item layout:
I have several items, SearchList, which contains a collection of Search, which contains a collection of DataSet (sort of, but that is beside the point). What I am having difficulty with is styling each node level the way I want. I am using MVVM, and the TreeViews ItemsSource property is set to an ObservableCollection of SearchListViewModels which in turn contain my objects all the way down the object tree.
I can successfully style the SearchList HierarchicalDataTemplate to display them correctly. Where I get hung up is on SearchTerm nodes styling. I want the DataSets to be represented in a wrap panel or uniform grid (I haven't decided yet) to the right of the SearchTerm content area. I have modified a TreeViewItem control template to behave this way I think), however if I set it in the ItemContainerStyle property of the Search HierarchicalDataTemplate, it does nothing. All that gets displayed is the content for the Search.
My Altered TreeViewItem Template
<Style TargetType="{x:Type TreeViewItem}" x:Key="AlteredTreeViewItem">
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
MinWidth="19" />
<ColumnDefinition Width="0.414*" />
<ColumnDefinition Width="0.586*"/>
</Grid.ColumnDefinitions>
<Border x:Name="Bd" HorizontalAlignment="Stretch"
Grid.Column="1" Grid.ColumnSpan="1" Background="#7F058956">
<ContentPresenter x:Name="PART_Header" Margin="10,0" />
</Border>
<WrapPanel x:Name="ItemsHost"
Grid.Column="2" IsItemsHost="True"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
My Search Hierarchical Data Template
<HierarchicalDataTemplate DataType="{x:Type local:SearchViewModel}" ItemsSource="{Binding MySearch.Custodians}" ItemContainerStyle="{StaticResource AlteredTreeViewItem}">
<TextBlock Text="{Binding MySearch.SearchName}" Foreground="Black" FontFamily="Arial" FontSize="16"/>
</HierarchicalDataTemplate>
Surely it is possible to both style differently and have child items laid out differently? How can this be achieved?
It seems that you are pretty close to what you're after. I tried to recreate your scenario based on the code you posted and I noted some problems with it (which of course are based on my interpretation of the code you posted)
You are missing the ContentSource="Header" part of the ContentPresenter
I think you are applying the ItemContainerStyle at the wrong HierarchicalDataTemplate level. It should be specified on the parent in order to affect the children (in your case SearchListViewModel).
The default Template for TreeViewItem lays out the ContentPresenter in an Auto sized ColumnDefinition so the WrapPanel won't succesfully wrap unless you modify the ItemContainerStyle for the parent as well. I changed it to a UniformGrid in my sample below
With the changes from above and a few other things I got a result that looks like this which hopefully is pretty close to what you're after
I uploaded the sample solution here: https://www.dropbox.com/s/4v2t8imikkagueb/TreeViewAltered.zip?dl=0
And here is the Xaml code for it (too much code to post it all..)
<Window.Resources>
<!-- DataSet-->
<HierarchicalDataTemplate DataType="{x:Type data:DataSet}">
<Border BorderThickness="3"
BorderBrush="Gray"
Background="Green">
<TextBlock Text="{Binding Path=Tables[0].TableName}"
Margin="5"/>
</Border>
</HierarchicalDataTemplate>
<!-- SearchViewModel -->
<HierarchicalDataTemplate DataType="{x:Type viewModel:SearchViewModel}"
ItemsSource="{Binding DataSets}">
<TextBlock Text="{Binding DisplayName}"
Foreground="Black"
FontFamily="Arial"
FontSize="16"/>
</HierarchicalDataTemplate>
<!-- SearchListViewModel -->
<HierarchicalDataTemplate DataType="{x:Type viewModel:SearchListViewModel}"
ItemsSource="{Binding SearchList}">
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="19" />
<ColumnDefinition Width="0.414*" />
<ColumnDefinition Width="0.586*"/>
</Grid.ColumnDefinitions>
<Border x:Name="Bd"
HorizontalAlignment="Stretch"
Grid.Column="1"
Grid.ColumnSpan="1"
Background="#7F058956">
<ContentPresenter x:Name="PART_Header"
ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Border>
<UniformGrid x:Name="ItemsHost"
Grid.Column="2"
Columns="3"
IsItemsHost="True"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<TextBlock Text="{Binding DisplayName}"
FontSize="20"/>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView ItemsSource="{Binding SearchListViewModels}" />
</Grid>
Something I learnt a long time ago when trying to create a similar interface was that you are better using a ListBox than a TreeView.
Why?
If you only have one level of expansion (as it appears from your sample) you will a lot more control of the layout as you have a single DataTemplate to style.
It is lot easier to customize a ListBox than a TreeView as you do not have be concerned with the GridViewColumnHeader and GridViewColumnPresenters etc.
To get the expansion part (which is why you initially selected a TreeView), simply use a Grid with two rows defined and an Expander in the second row bound to the IsChecked property of a ToggleButton. See the example that I pulled from my Log Viewer.
<DataTemplate>
<Grid Margin="0,0,0,3" Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30" SharedSizeGroup="SSG_TimeIcon"/>
<ColumnDefinition Width="120" SharedSizeGroup="SSG_Time"/>
<ColumnDefinition Width="30" SharedSizeGroup="SSG_LevelIcon"/>
<ColumnDefinition Width="70" SharedSizeGroup="SSG_Level"/>
<ColumnDefinition Width="*" SharedSizeGroup="SSG_Message"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- ProgramTime -->
<Rectangle Grid.Column="0" Grid.Row="0" Margin="0,0,0,0" Width="16" Height="16" VerticalAlignme="Top" HorizoalAlignme="Stretch" Fill="{StaticResource Icon_Timer}"/>
<TextBlock Grid.Column="1" Grid.Row="0" Margin="5,0,0,0" VerticalAlignme="Top" HorizoalAlignme="Stretch" Text="{Binding Path=TimeStamp, Converter={StaticResource ObjectToStringConverter}}" ToolTip="{Binding Path=ProgramTime}"/>
<!-- Level -->
<Rectangle Grid.Column="2" Grid.Row="0" Margin="10,0,0,0" Width="16" Height="16" VerticalAlignme="Top" HorizoalAlignme="Stretch" Fill="{Binding Path=Level, Converter={StaticResource MappingConverterNinjaLogLevelEnumToBrushResource}}"/>
<TextBlock Grid.Column="3" Grid.Row="0" Margin="5,0,0,0" Text="{Binding Path=LevelFriendlyName}" VerticalAlignme="Top" HorizoalAlignme="Stretch"/>
<!-- Message -->
<StackPanel Grid.Column="4" Grid.Row="0" Margin="10,0,0,0" Orieation="Horizoal" >
<TextBlock Margin="0,0,0,0" Text="{Binding Path=LogMessage}" TextWrapping="Wrap" VerticalAlignme="Top" HorizoalAlignme="Stretch"/>
<ToggleButton x:Name="ExpandExceptiooggleButton" VerticalAlignme="Top" Margin="5,0,0,0" IsChecked="False"
Coe="Show Details" Tag="Hide Details" Style="{StaticResource TextButtonStyle}"
Foreground="{StaticResource BlueBrush}" Background="{StaticResource RedBrush}"
Visibility="{Binding Path=HasException, Converter={StaticResource BoolToVisibilityConverter}}" />
</StackPanel>
<Expander IsExpanded="{Binding Path=IsChecked, ElemeName=ExpandExceptiooggleButton}" Style="{StaticResource CoeExpanderStyle}"
Margin="10,0,0,0" Grid.Column="4" Grid.Row="1">
<Border BorderBrush="{StaticResource DarkGreyBrush}" BorderThickness="1,0,0,0">
<TextBlock Text="{Binding Path=Exception}" Margin="5,0,0,0"/>
</Border>
</Expander>
</Grid>
</DataTemplate>
Can you see how much easier it is to define a header and expandable body. If you do have a need for nested data, add a Level property your view model (you are using MVVM aren't you?!) and then create a IValueConverter that returns a Margin (i.e. Thickness) to fake the indent.