Silverlight TreeViewItem width change - silverlight

I was asked to create custom TreeView based on basic TreeView from SDK. It all works, problem is: nodes/leaves do not stretch to their content, their width is always the same. Here's xaml markup:
<Grid xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:sdk='http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk'>
<Grid.Resources>
<Style x:Key='TreeViewChildStyle' TargetType='sdk:TreeViewItem'>
<Setter Property='HorizontalContentAlignment' Value='Stretch'/>
<Setter Property='Background' Value='Blue'/>
</Style>
<sdk:HierarchicalDataTemplate x:Key='ChildTemplate' x:Name='ChildTemplate'>
<TextBlock HorizontalAlignment='Stretch' Text='{Binding Path=ChildPath}'/>
</sdk:HierarchicalDataTemplate>
<sdk:HierarchicalDataTemplate x:Key='NameTemplate' ItemsSource='{Binding Path= ChildrenCollectionPath}' x:Name='NameTemplate' ItemTemplate='{StaticResource ChildTemplate}'>
<TextBlock HorizontalAlignment='Stretch' Text='{Binding Path=ParentPath}' Width='1000'/>
</sdk:HierarchicalDataTemplate>
</Grid.Resources>
<sdk:TreeView Height='Auto' Background='Red' ItemContainerStyle='{StaticResource TreeViewChildStyle}' Name='treeView1' ItemTemplate='{StaticResource NameTemplate} VerticalAlignment='Stretch' HorizontalAlignment='Stretch' BorderThickness='0'/>
</Grid>
I've already tried setting ItemContainer width in code behind, setting TextBlocks' width to 'Auto', setting ItemContainer width in style markup. Nothing works, TreeViewItems are always same width and it's way too narrow.
Edit: Yes, there is SDK namespace added to grid, something just happened to editor and it's not shown, can't help it.
Edit2: The TreeView actually changes its width to given value, yet, its Items are still not scaling.

Try to define a Grid Row or Column and set the Height/Width to "*" so it will use as much space it can.
<Grid.RowDefintions>
<RowDefintion Height="*" />
</Grid.RowDefintions>
<Grid.ColumnDefinitons>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

Related

How to prevent ItemsControl from horizontally stretching to fit children

I have an ItemsControl, nothing fancy:-
<ItemsControl ItemsSource="{Binding ...}"
ItemTemplate="{StaticResource ...}" />
The ItemTemplate contains the following XAML:-
<Border BorderThickness="0,0,0,1"
BorderBrush="LightGray"
Padding="0,2,0,2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"
SharedSizeGroup="Prompt" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding ...}" />
<NumericUpDown Grid.Column="1"
Width="75"
Text="{Binding ...}" />
</Grid>
</Border>
This produces a UI looking like this:-
However if the text in the TextBlock is very long, it pushes the NumericUpDown off the r.h. edge of the ItemsControl, e.g.:-
I was hoping that once the NumericUpDown had been "pushed up" against the r.h. edge of the ItemsControl, the TextBlock would then start getting truncated. I assume the current behaviour is due to the ItemsControl using a StackPanel as its items presenter. How can I get it to do what I want?
When you are using SharedSizeGroup with Grid.IsSharedSizeScope="True" the column's Star sizing is treated as Auto, more not official informations here.
The IsSharedSizeScope should not be used for arranging the controls described in the question. You should remove all SharedSizeGroup attributes and set the ItemsControl's HorizontalAlignment to Left.
I think that you might want to try setting the Control.HorizontalContentAlignment Property to Stretch on your ItemsControl. According to the linked page, this:
Gets or sets the horizontal alignment of the control's content.
In plain English, this means that it should set the Width of the rendered children, or items, to the same Width as the ItemsControl.
After a lot of running into dead-ends thinking I could resolve this by changing the ItemsPresenter or ItemsPanel, I ended up using a DockPanel within my ItemTemplate, instead of the grid:-
<Border BorderThickness="0,0,0,1"
BorderBrush="LightGray"
Padding="0,2,0,2">
<DockPanel LastChildFill="true">
<NumericUpDown DockPanel.Dock="Right"
Width="75"
Text="{Binding ...}" />
<TextBlock Text="{Binding ...}" />
</DockPanel>
</Border>
I'm not entirely sure why the DockPanel respects the size of the parent ItemsControl, while the Grid was happy to horizontally "overrun" off the edge. This is an aspect of WPF that I still struggle with - which controls' sizes are affected by their parent, and which are affected by their children's sizes!

How to make scrollviewer work with Height set to Auto in WPF?

I have learned that if the height of a grid row, where the ScrollViewer resides, is set as Auto, the vertical scroll bar will not take effect since the actual size of the ScrollViewer can be larger than the height in sight. So in order to make the scroll bar work, I should set the height to either a fixed number or star height
However, I now have this requirement, that I have two different views reside in two grid rows, and I have a toggle button to switch between these two views: when one view is shown, the other one is hidden/disappeared. So I have defined two rows, both heights are set as Auto. And I bind the visibility of the view in each row to a boolean property from my ViewModel (one is converted from True to Visible and the other from True to Collapsed. The idea is when one view's visibility is Collapsed, the height of the grid row/view will be changed to 0 automatically.
The view show/hidden is working fine. However, in one view I have a ScrollViewer, which as I mentioned doesn't work when the row height is set as Auto. Can anybody tell me how I can fulfill such requirement while still having the ScrollViewer working automatically`? I guess I can set the height in code-behind. But since I am using MVVM, it would require extra communication/notification. Is there a more straightforward way to do that?
In MVVM, the way that worked for me was to bind the height of the ScrollViewer to the ActualHeight of the parent control (which is always of type UIElement).
ActualHeight is a read-only property which is only set after the control has been drawn onto the screen. It may change if the window is resized.
<StackPanel>
<ScrollViewer Height="{Binding Path=ActualHeight,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UIElement}}">
<TextBlock Text=Hello"/>
</ScrollViewer>
</StackPanel>
But what if the parent control has an infinite height?
If the parent control has an infinite height, then we have a bigger problem. We have to keep setting the height of all parents, until we hit a control with a non-infinite height.
Snoop is absolutely invaluable for this:
If the "Height" for any XAML element is 0 or NaN, you can set it to something using one of:
Height="{Binding Path=ActualHeight, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UIElement}}"
VerticalAlignment="Stretch"
Height="Auto"
Hint: Use VerticalAlignment="Stretch" if you are a child of a Grid with a <RowDefinition Height="*">, and the Binding RelativeSource... elsewhere if that doesn't work.
If you're interested, here is all of my previous attempts to fix this issue:
Appendix A: Previous Attempt 1
Can also use this:
Height="{Binding Path=ActualHeight, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=StackPanel}}"
Appendix B: Previous Attempt 2
Useful info: see Auto Height in combination with MaxHeight.
If nothing seems to work, it's probably because the ActualHeight of the parent is either 0 (so nothing is visible) or huge (so the scrollviewer never needs to appear). This is more of a problem if there are deeply nested grids, with a scrollviewer right at the bottom.
Use Snoop to find the ActualHeight of the parent StackPanel. In properties, filter by the word "Actual", which brings back ActualHeight and ActualWidth.
If ActualHeight is zero, give it a minimum height using MinHeight, so we can at least see something.
If ActualHeight is so huge that it goes off the edge of the screen (i.e. 16,000), give it a reasonable maximum height using MaxHeight, so the scrollbars will appear.
Once the scrollbars are appearing, then we can clean it up further:
Bind the Height of the StackPanel or Grid to the ActualHeight of the parent.
Finally, put a ScrollViewer inside this StackPanel.
Appendix C: Previous Attempt 3
It turns out that this can sometimes fail:
Height="{Binding Path=ActualHeight, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=StackPanel}}"
The reason? It the binding fails, the height will be zero and nothing will be seen. The binding can fail if we are binding to an element which is not accessible. The binding will fail if we are going up the visual tree, then down to a leaf node (e.g. up to the parent grid, then down to the ActualHeight of a row attached to that grid). This is why binding to the ActualWidth of a RowDefinition simply won't work.
Appendix D: Previous Attempt 4
I ended up getting this working by making sure that Height=Auto for all of the parent elements from us to the first <Grid> element in the UserControl.
Change Height from Auto to *, if you can.
Example:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="525">
<StackPanel Orientation="Horizontal" Background="LightGray">
<Grid Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Auto" x:Name="_scroll1">
<Border Height="300" Background="Red" />
</ScrollViewer>
<TextBlock Text="{Binding ElementName=_scroll1, Path=ActualHeight}" Grid.Row="1"/>
</Grid>
<Grid Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Auto" x:Name="_scroll2">
<Border Height="300" Background="Green" />
</ScrollViewer>
<TextBlock Text="{Binding ElementName=_scroll2, Path=ActualHeight}" Grid.Row="1"/>
</Grid>
</StackPanel>
</Window>
I've had similar problem, taking me hours to figure out the solution. What solved it was using a Dockpanel as parent container instead of a StackPanel. Just specify all children to dock to top if the functionality should be similar to vertical stackpanel. Consider using LastChildFill="False" in the Dock XAML which is'n default.
So instead of:
<StackPanel Orientation="Horizontal">
<Textbox>SomeTextBox</Textbox>
<Scrollviewer/>
</StackPanel>
Try:
<DockPanel LastChildFill="False">
<Textbox DockPanel.Dock="Top">SomeTextBox</Textbox>
<Scrollviewer DockPanel.Dock="Top"/>
</DockPanel>
You can either set a fix height on your ScrollViewer but then you have to consider that the second row of your grid will have that height too since row's first child will be the ScrollViewer and row's height is auto, or you bind the height of ScrollViewer to another control in your layout. We don't know how your layout looks alike.
At the end if you don't like neither of both just set the row's height to * as swiszcz suggested or hack wpf write your own custom panel that will be able to layout everything possible in every parallel universe or something like that. :)
What I discover is that you have to put your ScrollViewer within a container that has Height=Auto or you get his parent Heigh Actual Size and apply it to that container.
In my case I have UserControl like
<Grid Margin="0,0,0,0" Padding="0,2,0,0">
<ScrollViewer Height="Auto" ZoomMode="Disabled" IsVerticalScrollChainingEnabled="True" VerticalAlignment="Top"
HorizontalScrollMode="Enabled" HorizontalScrollBarVisibility="Disabled"
VerticalScrollMode="Enabled" VerticalScrollBarVisibility="Visible">
<ListView ItemsSource="{x:Bind PersonalDB.View, Mode=OneWay}" x:Name="DeviceList"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ItemTemplate="{StaticResource ContactListViewTemplate}"
SelectionMode="Single"
ShowsScrollingPlaceholders="False"
Grid.Row="1"
Grid.ColumnSpan="2"
VerticalAlignment="Stretch"
BorderThickness="0,0,0,0"
BorderBrush="DimGray">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel AreStickyGroupHeadersEnabled="False" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate x:DataType="local1:GroupInfoList">
<TextBlock Text="{x:Bind Key}"
Style="{ThemeResource TitleTextBlockStyle}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</ScrollViewer>
</Grid>
And I add it dinamically to ContentControl which is within a Page.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="0,0,12,0">
<Grid.RowDefinitions>
<RowDefinition Height="70" />
<RowDefinition Height="*" MinHeight="200" />
</Grid.RowDefinitions>
<Grid Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" >
<ContentControl x:Name="UIControlContainer" />
</Grid>
</Grid>
Notice that Heigh of the Row is *
When I populate ContentControl I use this code in Loaded event
UIControlContainer.Content = new UIDeviceSelection() {
VerticalAlignment = VerticalAlignment.Stretch,
HorizontalAlignment = HorizontalAlignment.Stretch,
Height = UIControlContainer.ActualHeight,
Width = UIControlContainer.ActualWidth
};
And also when ContentControl changes its size you have to update size of the UserControl.
UIControlContainer.SizeChanged += UIControlContainer_SizeChanged;
private void UIControlContainer_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (UIControlContainer.Content != null)
{
if (UIControlContainer.Content is UserControl)
{
(UIControlContainer.Content as UserControl).Height = UIControlContainer.ActualHeight;
(UIControlContainer.Content as UserControl).Width = UIControlContainer.ActualWidth;
}
}
}
Enjoy!
P.S. Acctually I did it for UWP.

Partially templated ListBox.ItemTemplate

I'm creating a custom control and I'm trying to create partially specified template for list box items. The template has some predefined parts and there should be another part that can be templated when using the control.
For this I have created a dependency property named SuggestionItemTemplate like so:
public static readonly DependencyProperty SuggestionItemTemplateProperty =
DependencyProperty.Register("SuggestionItemTemplate",
typeof(DataTemplate),
typeof(AutoSuggestTextBox),
new PropertyMetadata(null));
In my custom controls' generic.xaml I have:
<Style TargetType="local:AutoSuggestTextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:AutoSuggestTextBox">
<Grid>
<ListBox x:Name="ItemsControl">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0"
ContentTemplate="{TemplateBinding SuggestionItemTemplate}"
Content="{Binding}" />
<ToggleButton Grid.Column="1"
x:Name="DetailsHover"
ClickMode="Hover"
Style="{StaticResource DetailsToggleButtonStyle}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Unfortunatelly, this does not work as it's not possible to use TemplateBinding from inside ContentPresenter nested into DataTemplate. (The member "SuggestionItemTemplate" is not recognized or is not accessible.)
I also tried to use ancestor binding (available in Silverlight 5) like:
<ContentPresenter Grid.Column="0"
ContentTemplate="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=local:AutoSuggestTextBox}, Path=SuggestionItemTemplate}"
Content="{Binding}" />
But this results in binding error:
Error: System.Exception: BindingExpression_CannotFindAncestor
I suppose this happens because I'm inside ControlTemplate of my custom control and "local:AutoSuggestTextBox" is not defined anywhere in the style.
The third option that I tried was to apply ContentTemplate in OnApplyTemplate override but this also doesn't work:
var cp = itemsControlElement.ItemTemplate.LoadContent() as ContentPresenter;
cp.ContentTemplate = SuggestionItemTemplate;
In all cases, I get my grid with two columns, toggle button is visible but content presenter simple prints out view model's type name. (I believe this is the default behavior if the ContentTemplate is null).
Is this even possible to do? Are there any other ways to specify a partial template and then only add customized template part when necessary?
As a workaround for now, I can specify
ItemTemplate="{TemplateBinding SuggestionItemTemplate}"
for the list box and then copy/paste the generic template everywhere I use this control. But this is the behavior I'm hoping to avoid in the first place.
Thanks!
edit: I used the code tags for all blocks of code, but they're not highlighted for some reason. :/
It is possible to walk through Visual Ancestors in the OnApplyTemplate method, find your ContentPresenter(s) and set the ItemTemplate on that. To my mind, this is fine for a single item, but not so much in an ItemsControl scenario.
You could achieve what you are after using your own custom Control. Just give it a Content dependency property of type Object, and a Template DP of type DataTemplate (and multiples of the two if you fancy), and you can set up the root visual style and templates in the default style for your Control.
In this specific case, I would suggest that the best approach is to put your ToggleButton in the ListBoxItem template instead by customising the ListBox.ItemContainerStyle. It is easy to modify the default Control Template using Expression Blend, and the DataContext of the ToggleButton will not change, so the changes to your own logic should be minimal.
Edit: If you mean to use a number of different data templates, perhaps Implicit Data Templates will be more suitable.
I managed to solve this using a different approach. I used ancestor binding but instead of trying to reach the root control (my AutoSuggestTextBox) from the DataTemplate, I ask for a reference to my ListBox (here named ItemsControl).
However, since the ListBox doesn't have the SuggestionItemTemplate property, I sub-classed it to my own CustomListBox where I implemented that property. It all comes down to this code snippet:
<Style TargetType="local:AutoSuggestTextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:AutoSuggestTextBox">
<Grid>
<local:CustomizableListBox x:Name="ItemsControl"
SuggestionItemTemplate="{TemplateBinding SuggestionItemTemplate}">
<local:CustomizableListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0"
ContentTemplate="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=local:CustomizableListBox}, Path=SuggestionItemTemplate}"
Content="{Binding}" />
<ToggleButton Grid.Column="1"
x:Name="DetailsHover"
ClickMode="Hover"
Style="{StaticResource DetailsToggleButtonStyle}" />
</Grid>
</DataTemplate>
</local:CustomizableListBox.ItemTemplate>
</local:CustomizableListBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

wpf layout help

I have the following xaml which resides in a wpf user control -
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="*" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<TextBox
x:Name="MyTxt"
TextWrapping="WrapWithOverflow"
Grid.Row="0"
/>
<ListView
x:Name="MyList"
ItemsSource="{Binding}"
Grid.Row="1"
/>
<Label
Grid.Row="2"
/>
</Grid>
This control is nested within a grid in a view. I would like to have the text box be a set height at the top of the grid, the label at the bottom showing as a fixed height at the bottom of the grid. I want the list view to fill the rest of the screen area.
The problem that I am having is the listview does not size correctly. If I have too many records that show up in it, it extends beyond the window and no scroll bars are available to scroll down. I therefore cannot get to the bottom to see the vertical scroll bar if the data stretches off to the right of the screen.
I was able to set the listview to a fixed height and that worked, but I would like it to be more dynamic and resize with the window if possible.
Does anyone have any tips that might get the sizing correct?
Thanks for any thoughts.
EDIT - Here is the xaml for the containing grid in the mainwindow view. this was adapted from the article by Josh Smith here
<Grid>
<Border
Style="{StaticResource MainBorderStyle}"
>
<HeaderedContentControl
Content="{Binding Path=Workspaces}"
ContentTemplate="{StaticResource WorkspacesTemplate}"
/>
</Border>
</Grid>
I do have the scrollviewer properties set as mentioned in some of the answers below.
Here is the datatemplate for the workspace
<DataTemplate x:Key="WorkspacesTemplate">
<TabControl
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource ClosableTabItemTemplate}"
Margin="4"
/>
</DataTemplate>
Can you just add these properties to the listview?
ScrollViewer.CanContentScroll = "True"
ScrollViewer.VerticalScrollBarVisibility="Visible" <!-- or "Auto" -->
Everything else looks ok to me. You have the 3 rows, 2 of which are absolute, the other stretching. You also have the listview in the 2nd row, so it should stretch with it.
if that doesn't work, try wrapping the ListView in a scrollviewer
<ScrollViewer>
<ListView/>
</ScrollViewer>
What is the VerticalAlignment of a ListBox by default? You might need to set the vertical alignment to Stretch.
<ListView
x:Name="MyList"
ItemsSource="{Binding}"
Grid.Row="1"
VerticalAlignment="Stretch"
/>
I was able to get it working. If I change the containing grid in the main window to use a ContentControl instead of a HeaderedcontentControl, it works as expected.
Thank for any help.

Listboxitem not aligning items properly

Ok I got the following DataTemplate:
Style="{StaticResource LBStyle}" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Label Content="{Binding Name}" x:Name="txt" Grid.Column="0"></Label>
<StackPanel Orientation="Vertical" Grid.Column="1">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{z:txt text=time}" Width="50">:</TextBlock>
<TextBlock Text="{Binding Path=Value, Converter={StaticResource DecFix}}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Width="50">
<TextBlock Text="Norm.">:</TextBlock>
<TextBlock Text="{Binding Path=NormaalWaarde, Converter={StaticResource DecFix}}" />
</StackPanel>
</StackPanel>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsCurrentStep}" Value="True">
<Setter TargetName="txt" Property="FontWeight" Value="Bold"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
Basically what I want is for each item to have some text on the left side, which stretches with the width of the listbox and 2 values on the right side, which stays on the right side.
I've tried this with many different kind of panels, grids etc. And they all seem to just put the values on the right side wrapped together to the text on the left side like this:
link text
(please use the link to see what I mean, I cannot post pictures yet)
If i put the same datatemplate standalone somewhere else it just does what it should do. Does anyone have a suggestion?
Edit: I put a gridsplitter between the listbox and the rest of the window and it looks like the listbox is stretching indefinately. This is how the listbox is positioned amongst other elements in my window: (the listbox is in the tagger usercontrol)
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="2.5*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<vid:TagControl x:Name="Tagger" Grid.Column="0"></vid:TagControl>
<GridSplitter ResizeDirection="Columns" Width="20" />
<vid:DShowPlayer x:Name="DShowPlayer1" Grid.Column="1"></vid:DShowPlayer>
</Grid>
The problem here is certainly not related to your DataTemplate at all, or whether or not you are using data binding. Something in the ListBox or ListBoxItem style or ControlTemplate is causing a control to have HorizontalAlignment not set to "Stretch" at some level. (Or you could be using custom Measure or Arrange code that ignores HorizontalAlignment at some level)
I would suspect your Style="{StaticResource LBStyle} is the culprit, or some other ListBox property that isn't shown.
The default ListBox style contains a template with a Border and a ScrollViewer, none of which contains a HorizontalAlignment setting
The default ListBox ItemsPanel template consists of a StackPanel, which also doesn't contain a HorizontalAlignment setting
The default ListBoxItem template contains a template with a Border and ContentPresenter. Only the Border contains a HorizontalAlignment setting, and it is set (via a style setter) to the containing ListBox's HorizontalContentAlignment, which you have set to "Stretch".
If run in isolation the code you posted works fine. Search your style (and other properties, code-behind settings, etc) for any template replacement or setting that overrides the default HorizontalAlignment handling.
If the problem isn't apparent at first, remove settings one at a time until it stops working, then look closer at what you removed.
None of the DataTemplate examples I can find state this explicitly, but it appears to be the case that DataTemplates only apply when your list items come from an ItemsSource binding. If you directly populate the Items collection, the DataTemplate isn't used.
Adding an ItemTemplate in Expression Blend, the command text reads "Generated Item Template" - which seems to mean the template is only used when the item is generated indirectly.
And every example I can find uses a data binding for the item source.
You should use Grid instead of DockPanel with 3 columns, 1st column as 1 * , 2nd and 3rd as fixed length...

Resources