how to measure UIElement created from hierachical datatemplate - silverlight

folks, I am about to print a hierachical data from Silverlight 5. I use a resource dictionary to define the layout of the data. The main xaml segments like this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MSCE.SL.ArchievementAssessment"
xmlns:stat="clr-namespace:MSCE.SL.ArchievementAssessment.Statistics">
<DataTemplate DataType="stat:Level1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center"/>
<ItemsControl Grid.Column="1" ItemsSource="{Binding Children}"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="stat:Level2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center"/>
<ItemsControl Grid.Column="1" ItemsSource="{Binding Children}"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="Level3ItemTemplate">
....
</DataTemplate>
<DataTemplate DataType="stat:Level3">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center"/>
<ListBox Grid.Column="1" ItemsSource="{Binding Children}"
ItemTemplate="{StaticResource Level3ItemTemplate}"/>
</Grid>
</DataTemplate>
</ResourceDictionary>
then I use those templates in printing code as follow:
void Print(object para)
{
PrintDocument pd = new PrintDocument();
List<FrameworkElement> pages = null;
int pageIndex = 0;
pd.PrintPage += (s, e) =>
{
if (pages == null)
{
pages = CreatePages(e.PrintableArea);
}
e.PageVisual = pages[pageIndex] ;
pageIndex++;
e.HasMorePages = pageIndex < pages.Count;
};
pd.Print("statistics");
}
List<FrameworkElement> CreatePages(Size printableArea)
{
// create result pages' container
List<FrameworkElement> pages=new List<FrameworkElement>();
// get resources for printing
IEnumerable<Level1> data=...// detail ignored, get data from ViewModel
ResourceDictionary res=... // detail ignored, get data template from assembly
// create page root visual and
// merge printing templates' resource into root's resource dictionary
StackPanel root=new StackPanel();
root.ResourceDictionary.MergedDictionaries.Add(res);
// fetch data template of data Level1
var level1Template=root.Resources[new DataTemplateKey(typeof(Level1))] as DataTemplate;
// trace height of available space
double availableContentHeight=printableArea.Height;
foreach(var lvl1 in data)
{
// create UI of Level1 using template
var ui=level1Template.LoadContent() as FrameworkElement;
ui.DataContext = data;
ui.OnApplyTemplate();
// measure the size requirement of this Level1's UI
ui.Measure(printableArea);
// if available space is not enough, add the last page to pages container
// and create a new page to contain new created Level1 UI
if(ui.DesireSize.Height>availableContentHeight)
{
pages.Add(root);
root=new StackPanel();
availableContentHeight=printableArea.Height;
}
root.Children.Add(ui);
availableContentHeight-=ui.DesiredSize.Height;
}
pages.Add(root);
return pages;
}
The problem occurs at Measuring. It should contain about three pages. But the sum of the heights of all Level1 UIs based on Measure results occupy only half a page. So the printer prints always only one page and cuts many content down. I think that the Measure method for Level1 UI returns only the height of his title(TextBlock Text="{Binding Name}"), it doesn't include the space requirements of level1's children and certainly the space requirements of level2's children.
At the begining, I didn't put the statement ui.OnApplyTemplate(). After the problem occured, I thought that this might preload all children content and I could get right measuring result. But in the fact it changes nothing.
Now, my thought is, either preloading the whole visual tree for data Level1 before adding it to PageVisual of PringPageEventArgs to get right measuring result, or write a hierachical measuring method to measure Level1 UI from the bottom (level3's children) to top.
Because that my actual data templates are more complicated than the above ones, the second method is time comsumed and is prone to introduce bugs. So I hope someone to teach me how to accomplish the first road or direct me to a clear solution.

Well, after some days, I had to handle the measuring problem with proximate algorithm. I assume that every detailed level3 row occupys only one row and then measure height of each row and sum all height values up. Without accruate measuring, not perfect, but It can cope with the case.

Related

WPF binding to a number of objects only known at runtime

I'm trying to understand the limits of binding in WPF (if any). I understand how binding to a pre-defined number of objects in XAML works, e.g.:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding MyText}" Grid.Row="1" Grid.Column="0"/>
</Grid>
(I used TextBlock just as an example, it could have been a Button or any other element)
Now, suppose that, instead of a single TextBlock, I need to display a number of them, but the exact number will only be known at run-time, together with the text to be written in each TextBlock (and possibly other attributes I may want to bind). Is this something that can be achieved in practice?
To display multiple items in WPF, you would typically use the base ItemsControl class or one of the classes that derives from it. Here is a diagram of the inheritance hierarchy, you can use ItemsControl when all you need is basic functionality and one of its derived classes when you need more:
ItemsControl and its children provide an ItemsSource attribute that allows you to bind your collection (usually an ObservableCollection). However, for user-defined types, you will also need to provide a data template to tell the control how to display the contents.
For example, say you had a simple class like the following:
public class Message
{
public string MyText { get; set; }
}
And you create a list of them (in your case you would populate the list at run time):
Messages = new List<Message>
{
new Message { MyText = "SomeText1" },
new Message { MyText = "SomeText2" },
new Message { MyText = "SomeText3" },
};
You could display them all using the following xaml:
<ItemsControl ItemsSource="{Binding Messages}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding MyText}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
In side the DataTemplate you would add the controls you use to display the properties of your type and bind to them.
NOTES
Please note that the example above is the bare bones implementation just to show how to get started. Once you get more advanced, you may need to implement change notifications for your properties (i.e. INotifyPropertyChanged) and also for adding/removing items for your collection, etc.

Displaying a list of images that just fill their available space in an expandable cell

I've got a desktop GUI (VS2013, .NET 4.5.2) with a few levels of embedded grids. In one cell (which can be expanded in both dimensions using gridsplitters) I have this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListView Grid.Column="0" ItemsSource="{Binding Results.Info}"/>
<ListView Grid.Column="1" ItemsSource="{Binding Results.Images}"/>
</Grid>
In the MVVM-Light-supported view model:
public ObservableCollection<object> Images
{
get { return mImages; }
set { Set(() => Images, ref mImages, value); }
}
I load up this property with a sequence of text (captions) and images created this way:
var img = new Image
{
Source = new BitmapImage(new Uri(fullPathToPng)),
};
Images.Add(caption);
Images.Add(img);
...repeat until all captions and images added
The code above produces images large enough to cause the listview to display scrollbars, although dragging gridsplitters eventually lets me see whole images.
Here's what I'd like to happen: The images shrink to fill just the available space without causing the listview to display its scrollbars, and when gridsplitters are moved giving this cell more space, the images grow to fill just the newly-available space.
I'm not married to using a ListView to hold the captions/images sequence, but I do want the solution to respect MVVM. Thanks.
Turned out to be simple: I just needed to disable the ListView's horizontal scrolling:
<ListView Grid.Column="1" ItemsSource="{Binding Results.Images}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" />

WPF Zoom + Scrollbar?

I'm trying to zoom some contents within scrollviewer.
The zoom behavior I'm looking for is that of a RenderTransform+ScaleTransform. But this does not work with the ScrollViewer.
Using LayoutTransform+ScaleTransform, the scrollviewer does get affected (ContentTemplate1 only), but does not behave like a zoom.
Assuming ContentTemplate1/ContentTemplate2 cannot be changed (ie, 3rd party controls), how can I get zoom to work with a scrollviewer?
<Grid>
<Grid.Resources>
<!-- Content type 1 -->
<DataTemplate x:Key="ContentTemplate1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Background="DodgerBlue" Text="Left"/>
<TextBlock Grid.Column="1" Background="DarkGray" Text="Right"/>
</Grid>
</DataTemplate>
<!-- Content type 2 -->
<DataTemplate x:Key="ContentTemplate2">
<Viewbox>
<TextBlock Background="DodgerBlue" Text="Scale to fit" Width="100" Height="70" Foreground="White" TextAlignment="Center"/>
</Viewbox>
</DataTemplate>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TabControl>
<!-- Content 1 -->
<TabControl.Resources>
<ScaleTransform x:Key="ScaleTransform"
ScaleX="{Binding ElementName=ZoomSlider,Path=Value}"
ScaleY="{Binding ElementName=ZoomSlider,Path=Value}" />
</TabControl.Resources>
<TabItem Header="Content 1">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<ContentControl ContentTemplate="{StaticResource ContentTemplate1}" Margin="10" RenderTransformOrigin=".5,.5">
<!-- Affects scrollviewer, but does not behave like a zoom -->
<!--<FrameworkElement.LayoutTransform>
<StaticResource ResourceKey="ScaleTransform" />
</FrameworkElement.LayoutTransform>-->
<!-- Expected zoom behavior, but doesn't affect scrollviewer -->
<FrameworkElement.RenderTransform>
<StaticResource ResourceKey="ScaleTransform" />
</FrameworkElement.RenderTransform>
</ContentControl>
</ScrollViewer>
</TabItem>
<!-- Content 2 -->
<TabItem Header="Content 2">
<ContentControl ContentTemplate="{StaticResource ContentTemplate2}" Margin="10" RenderTransformOrigin=".5,.5">
<!-- Affects scrollviewer, but does not behave like a zoom -->
<!--<FrameworkElement.LayoutTransform>
<StaticResource ResourceKey="ScaleTransform" />
</FrameworkElement.LayoutTransform>-->
<!-- Expected zoom behavior, but doesn't affect scrollviewer -->
<FrameworkElement.RenderTransform>
<StaticResource ResourceKey="ScaleTransform" />
</FrameworkElement.RenderTransform>
</ContentControl>
</TabItem>
</TabControl>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<!-- Zoom -->
<Slider x:Name="ZoomSlider"
Width="100"
Maximum="5"
Minimum="0.1"
Orientation="Horizontal"
Value="1" />
<!-- Autofit -->
<CheckBox Content="Autofit?" x:Name="AutoFitCheckBox" />
</StackPanel>
</Grid>
If I understand correctly:
You want to zoom with the ZoomSlider slider?
You want scrollbars to appear if the content is too large to fit within its tab?
If so, it's LayoutTransform you want. That transformation is done before all elements are measured and laid out, and the ScrollViewer will be able to tell whether scrollbars are needed.
On my machine, the "Content 1" tab works as expected if you just switch to LayoutTransform (note that you have to zoom a lot before "Right" disappears off-screen, toggling the scrollbar):
"Content 2" requires a little more work. First of all, there's no ScrollViewer in that tab, so that needs to be added. Secondly, ContentTemplate2 uses a ViewBox, which stretches by default, so zooming won't have an effect until you zoom in really close. To disable the ViewBox' built-in "zooming", you can center the ContentControl container (using HorizontalAlignment/VerticalAlignment), which forces it to take up as little space as possible:
<TabItem Header="Content 2">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<ContentControl ContentTemplate="{StaticResource ContentTemplate2}" ...
HorizontalAlignment="Center" VerticalAlignment="Center" >
<FrameworkElement.LayoutTransform>
...
To make the zoomed elements get the exact RenderTransform look, we may as well stick with RenderTransform, and instead tell the ScrollViewer how to behave by implementing our own scrolling logic. This approach is based on this excellent tutorial:
https://web.archive.org/web/20140809230047/http://tech.pro/tutorial/907/wpf-tutorial-implementing-iscrollinfo
We create our own custom "ZoomableContentControl" which implements IScrollInfo and tell the ScrollViewer to get its scrolling logic from there (ScrollViewer.CanContentScroll = True). The magic happens in ArrangeOverride() where we play with ExtentWidth/ExtentHeight and RenderTransformOrigin.
public class ZoomableContentControl : ContentControl, IScrollInfo
{
public ZoomableContentControl()
{
this.RenderTransformOrigin = new Point(0.5, 0.5);
}
private ScaleTransform _scale = null;
private ScaleTransform Scale
{
get
{
if (_scale == null)
{
_scale = this.RenderTransform as ScaleTransform;
//RenderTransforms don't update the layout, so we need to trigger that ourselves:
_scale.Changed += (s, e) => { InvalidateArrange(); };
}
return _scale;
}
}
protected override Size ArrangeOverride(Size arrangeBounds)
{
Statics.MessageIfDebug("Arranging");
var layout = base.ArrangeOverride(arrangeBounds);
var scale = this.Scale;
if (scale != null)
{
//Because RenderTransforms don't update the layout,
//we need to pretend we're bigger than we are to make room for our zoomed content:
_extent = new Size(layout.Width * scale.ScaleX, layout.Height * scale.ScaleY);
_viewport = layout;
//Coerce offsets..
var maxOffset = new Vector(ExtentWidth - ViewportWidth, ExtentHeight - ViewportHeight);
_offset.X = Math.Max(0, Math.Min(_offset.X, maxOffset.X));
_offset.Y = Math.Max(0, Math.Min(_offset.Y, maxOffset.Y));
//..and move the zoomed content within the ScrollViewer:
var renderOffsetX = (maxOffset.X > 0) ? (_offset.X / maxOffset.X) : 0.5;
var renderOffsetY = (maxOffset.Y > 0) ? (_offset.Y / maxOffset.Y) : 0.5;
this.RenderTransformOrigin = new Point(renderOffsetX, renderOffsetY);
if (ScrollOwner != null)
{
ScrollOwner.InvalidateScrollInfo();
}
}
return layout;
}
#region IScrollInfo
//This is the boilerplate IScrollInfo implementation,
//which can be found in *the first half* of this tutorial:
//https://web.archive.org/web/20140809230047/http://tech.pro/tutorial/907/wpf-tutorial-implementing-iscrollinfo
//(down to and including SetHorizontalOffset()/SetVerticalOffset()).
//Note the bug reported by "Martin" in the comments.
...
Usage:
<TabItem Header="Content 1">
<ScrollViewer CanContentScroll="True"
HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<v:ZoomableContentControl ContentTemplate="{StaticResource ContentTemplate1}" Margin="10" >
<FrameworkElement.RenderTransform>
<StaticResource ResourceKey="ScaleTransform" />
</FrameworkElement.RenderTransform>
</v:ZoomableContentControl>
</ScrollViewer>
</TabItem>
<TabItem Header="Content 2">
<ScrollViewer CanContentScroll="True"
HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<v:ZoomableContentControl ContentTemplate="{StaticResource ContentTemplate2}" Margin="10" >
<FrameworkElement.RenderTransform>
<StaticResource ResourceKey="ScaleTransform" />
</FrameworkElement.RenderTransform>
</v:ZoomableContentControl>
</ScrollViewer>
</TabItem>
My first advice is to check what kind of zooming functionality you can with using a commercial third party zoom control that already have support for ScrollViewer and also has many additional zooming and panning features.
Now to the solution of your problem:
You can make your code work with using LayoutTransform, but you will need to set the size of the ScrollViewer's content to a fixed value.
Currently you have a Grid inside a ScrollViewer. The Grid does not have its size defined, so it takes all the space it can get. So if you now scale the Grid, for example by factor 2, this means that the content of the Grid is scaled by factor 2, but the Grid will still take all the space it can get. If you would specify the width of the Grid to be 500, then scaling it by 2, would make the Grid's width 1000. But if you say: Grid, you can take all space that the parent gives you and then scale the Grid, it will be still the same. This means that scaling the auto-sized content of ScrollViewer will not show scrollbars.
In your sample this is true until the content of the Grid (the first column with width = 150 + width of the "Right" text in the second column) exceed the available size - at that point the DesiredSize of the Grid would be bigger than the size that ScrollViewer can provide and ScrollViewer will show scrollbars.
For example:
1) let's say that when you start your application, scale is set to 1 and ScrollViewer provides 500 points horizontally for the Grid. The Grid shows first column with 150 points width and shows "Right" text without any scale. The second column is set to fill the remaining space - so: 500 - 150 = 350 points is used by second column.
2) Now user sets the scale to 2. The Grid scales the first column to 300 points. This means that the second column can now take only 200 points. The Grid also scales the "Right" text, but the content (300 of first column + width of text) still does not exceed 500 point that are provided by the ScrollViewer.
3) User now sets scale to 3. Now the total width of the content of the grid exceed 500 points and this means that ScrollViewer will show scroll bars.
So having autosized controls, ScrollViewer and scaling does not work well.
But if you would fix the size of the Grid to 500, than you would get much more predictable results when scaling and using ScrollViewer. For example if you would scale by 10%, than the Grid's size would be 550 and would already exceed the size of the ScrollViewer - so ScrollViewer would show scrollbars. This would also give you the expected behaviour when you would increase the size of the window - the size of the Grid would remain the same and at some point the scrollbars would disappear (when the window would be big enough to show the whole content of the scaled Grid).
To conclude: my advice to you is to set the fixed size to the content of ScrollViewer controls. If you have a fixed size window, that you can set the Width and Height based on that size. Otherwise you can set it dynamically when the control is first loaded:
You can change the XAML for the content control into:
<ContentControl Name="ContentControl1"
ContentTemplate="{StaticResource ContentTemplate1}"
Margin="10"
Loaded="ContentControl1_OnLoaded" >
And also add the ContentControl1_OnLoaded handled that would just set the size to the initial size:
private void ContentControl1_OnLoaded(object sender, RoutedEventArgs e)
{
ContentControl1.Width = ContentControl1.ActualWidth;
ContentControl1.Height = ContentControl1.ActualHeight;
}
Zooming and panning may seem like a very simple task to do. But my experience shows (I am the author of ZoomPanel control) that this task can quickly become very complicated.

ListView Data Binding for Windows 8.1 Store Apps

So I am trying to move a desktop program i made to an app for Windows 8.1 using Visual Studio 2013. Datagrid was deprecated for this release so I am trying to translate those over to a ListView. I previously used ListViews in other desktop applications, but it looks like a lot has changed. The problem I am having is populating my ListView from my database. I am connecting through a WCF Service and stepping through the code, I can see I am getting the right data, I just cant get it to appear in my ListView. My preferred end result would be a 'listview' with 3 columns of information which will be editable. Previously I would use ListView.View and then put a GridView in there for the columns. But it appears ListView.View is deprecated just like GridView.Columns.
here is my xaml for the ListView
<ListView x:Name="lvInventory" Grid.Row="2" Style="{StaticResource listViewStyle}" ItemsSource="{Binding}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Height="200" Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="tbName" Text="{Binding InventoryName}" Width="200" Foreground="#FF0E0D0D" />
<TextBox x:Name="tbQty" Grid.Column="1"/>
<TextBox x:Name="tbType" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
In my codebehind I am assigning the itemssource of my listview.
VMInventory inventory = new VMInventory();
inventory.GetList();
lvInventory.ItemsSource = inventory;
VMInventory is my ViewModel where I am getting my data from the WCF service and that looks like:
public async Task GetList()
{
this.connection = new InventoryModelEntities(new Uri(url));
var filteredList = from o in connection.Inventory
where o.Have == false
select o;
var query = await Task.Factory.FromAsync((filteredList as DataServiceQuery).BeginExecute(null, null),
(result) => (filteredList as DataServiceQuery).EndExecute(result)) as IEnumerable<Aurora.InventoryService.Inventory>;
this.inventoryList = query.ToList();
this.currentItem = 0;
this.onPropertyChanged("Current");
this.IsAtStart = true;
this.IsAtEnd = (inventoryList.Count == 0);
}
One last side note, I was able to add a textbox to the Grid and when I DataBind it to text="{Binding Current.InventoryName}" I am able to successfully bind it.
If i understand correctly your UI is not getting updated with values what ever your adding in ViewModel, but if you add some value in UI it is reflecting in the ViewModel.
If that is the case, the use ObserableCollection instead of list, and if your creating list every time, then you have to implement INotifyPropertyChanged in your ViewModel.
If you have done all this but still it is not updating then, your creating the list in asy Task, which is not a UI thread. If you want to update a UI from a non-Ui thread, then use update the UI using Dispatcher. You can find lot of examples to update the UI from non-UI thread using dispatcher

Padding text in listbox

var a1 = "HEL";
var a2 = "HELLO";
var a3 = "LLO";
var length = a2.Length+5;
listbox.Items.Add(a1.PadRight(length) +"End");
listbox.Items.Add(a2.PadRight(length) + "End");
listbox.Items.Add(a3.PadRight(length) + "End");
I have code like this to obviously pad all text so that the word End lines up.
The problem is I have to change the font from the wpf listbox from Segoe UI to Courier New to have this work. The rest of my app uses Segoe UI, so I think it looks weird here.
Is there any way to achieve the result with Segoe UI or maybe a similar font with correct spacing I could use, or maybe someone has some other smart solution i haven't even thought of? :-)
Thanks
edit
at the end of the day I want this to display to related items like this:
ITEM A -> ITEM B
ITEM X -> ITEM Y
ITEM C -> ITEM E
dont want to use gridview.
Feed the ListBox the two pieces of data separately, and use a data template. Here's how.
First, create a little class to represent each item you want to insert:
public class WordPair {
public string First { get; set; }
public string Second { get; set; }
}
(You probably already have a suitable class and/or collection in your application -- I assume those pairs of strings are coming from somewhere!)
Second, set your ListBox.ItemsSource to a collection of these things:
listBox.ItemsSource = new List<WordPair> {
new WordPair { First = "ITEM A", Second = "ITEM B" },
new WordPair { First = "ITEM X", Second = "ITEM Y" },
};
Again, this collection may already exist in your app.
Third, create a DataTemplate specifying the desired layout, and assign it to your ListBox.ItemTemplate:
<!-- in your Window.Resources section -->
<DataTemplate x:Key="AlignedPairs">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding First}" Grid.Column="0" />
<TextBlock Text="->" TextAlignment="Center" Grid.Column="1" />
<TextBlock Text="{Binding Second}" TextAlignment="Right" Grid.Column="2" />
</Grid>
</DataTemplate>
<ListBox Name="listBox" ItemTemplate="{StaticResource AlignedPairs}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
(I've guessed at the exact alignment you want for the items, but you can obviously tweak it.)
Note that you also need to set the HorizontalContentAlignment of the ListBoxItems to Stretch using ListBox.ItemContainerStyle. Otherwise each ListBoxItem will take up only the space it needs, resulting in all the Grid columns being minimal size and looking like a straight concatenation. Stretch makes each ListBoxItem fill the full width so the Grid columns are forced to grow accordingly.
<ListBox
x:Name="listBox" HorizontalContentAlignment="Right"/>
check it :)

Resources