I have a ListBox set up with automatic numbering as shown below. I want to format the number out front of each ListBoxItem so the numbers in all the rows are right aligned with each other. I figured I could use the item count to determine how many characters are in the index, using that info to set up a format in my viewmodel, and bind to it. Unfortunately I have not even figured out how to format a constant field width for my numbers. The ListBox will look a lot nicer with the contents lined up. So I need to know how to set up the format so I can bind to it.
<ListBox ItemsSource="{Binding Profiles}" SelectedItem="{Binding SelectedProfile, Mode=TwoWay}"
AlternationCount="{Binding Path=Profiles.Count}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0,0,5,0"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplatedParent.(ItemsControl.AlternationIndex)}"/>
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Your Profile type should have an Index property of some sort, which you should set. AlternationCount "enables alternating containers to have a unique appearance," so I believe you're not using that correctly. When you have that property added to your Profile type then you can do something for your ItemTemplate like:
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100">
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Right"
Margin="0 0 5 0"
Grid.Column="0"
Text="{Binding Index}"/>
<TextBlock Grid.Column="1"
Text="{Binding}" />
</Grid>
</DataTemplate>
Related
In my WPF application I have ListBox which contains a collection of items. One item can be added when a button is clicked and it is selected in the opened dialogue. As soon as a item is selected the dialogue closes and the item's image and name should be displayed in my ListBox. Unfortunately the Listbox does not update and nothing changes.
Usercontrol with Listbox:
<ListBox ItemsSource="{Binding BlButtonCollection, UpdateSourceTrigger=PropertyChanged}" VerticalContentAlignment="Stretch" SelectedItem="{Binding SelectedSticker}"
HorizontalContentAlignment="Stretch" ItemContainerStyle="{StaticResource ListBoxItemStyle}">
<ListBox.Resources>
<viewmodels1:BindingProxy x:Key="ProxyElement" Data="{Binding}" />
</ListBox.Resources>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="4" Rows="10"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1">
<Grid x:Name="f">
<Grid.RowDefinitions>
<RowDefinition Height="5*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="btnSelectArticle" Background="Transparent" Grid.RowSpan="2" BorderThickness="0"
Command="{Binding DataContext.ButtonClicked,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBox}}}"/>
<Image Height="1.5cm" HorizontalAlignment="Center" Source="{Binding ItemImage.ImageUrl, Converter={StaticResource ImageFormatConverter}}"/>
<TextBlock Text="{Binding ItemName}" Width="4cm" Height="0.8cm" TextWrapping="Wrap" Grid.Row="1" HorizontalAlignment="Center"/>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Controls with ListBoxes in main window:
<formats:OneXTwo x:Name="oneXTwo" BlButtonCollection="{Binding BlButtons_2}" IsBlVisible="Visible" Visibility="{Binding Are2StickersVisible}"
ButtonClicked="{Binding BlStickerButtonClickedCommand}"/>
<formats:ThreeXEight x:Name="threeXEight" BlButtonCollection="{Binding BlButtons_24}" IsBlVisible="Visible" Visibility="{Binding Are24StickersVisible}"
ButtonClicked="{Binding BlStickerButtonClickedCommand}"/>
<formats:FourXTen x:Name="fourXTen" BlButtonCollection="{Binding BlButtons_40, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" IsBlVisible="Visible" Visibility="{Binding Are40StickersVisible}"
ButtonClicked="{Binding BlStickerButtonClickedCommand}" SelectedSticker="{Binding SelectedBlSticker, Mode=TwoWay}" />
I should mention that I have three different formats and each format is a own user-control. Therfore, they are displayed in a shell-view and based on a ComboBox selection one format is displayed. If I am running the application, select a image nothing happens, but if I change the bound value of the textblock in the list view and switch it back to 'Itemname' the Image and Name are displayed.
Have you set the DataContext to a specific ViewModel?
ObservableCollection can only ensure the add/remove operation for items that can be updated to the UI. If you want to the item property to notify the UI, you should override the setter of the property and implement INotifyPropertyChanged.
I have some problems binding a ListBox to the elements of a collection in a collection.. Let me explain:
I have a collection, ObservableCollection<Test> named testsCollection. Every test contains an ObservableCollection<LogEvent> named LogEvents. Every LogEvent has a Message that I need to display in the ListBox.
I need to display every "Message" in every "LogEvent" in every "Test". It has to be displayed in a flat list so I'm using a ListBox.
Here's a summary of what I tried:
DataContext = testCollection; // testCollection is an ObservableCollection<Test>
The I put this in the XAML:
<ListBox ItemsSource="{Binding LogEvents}" ItemTemplate="{StaticResource stepItemTemplate}">
Finally, here's the ItemTemplate, stepItemTemplate:
<DataTemplate x:Key="stepItemTemplate">
<TextBlock Text="{Binding Message}"></TextBlock>
</DataTemplate>
This "works" but it only displays the Messages in the LogEvents of the first Test. But I need to display every Messages of every LogEvent of every Test.. And I don't know what to try anymore :(
You should Usser ItemsControl when you want to bind a scenario like this
<ListBox ItemsSource="{Binding testsCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Message}" FontSize="20" />
<ItemsControl ItemsSource="{Binding LogEvents}" Margin="0 20 0 0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Blue" BorderThickness="2">
<TextBlock Text="{Binding Message}" FontSize="20" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
I need to fix a list with elements that have different types. Each of the type has it's own datatype to represent the viewmodel for each type. The following code works for me, but for some reason the data inside gets truncated, to some value (looks like default). I need to remove this trancation.
Here is what I have. This code is in the control, that could be placed in a list as well (it could be doubled or tripled). But I Don't think it's relevant.
<ScrollViewer VerticalScrollBarVisibility="Visible">
<ListView DockPanel.Dock="Top" Name="testCaseResultListView"
ItemsSource="{Binding LogItems}"
ItemContainerStyleSelector="{StaticResource fixSideViewLogItemStyleSelector}"
SelectionMode="Single"
>
<ListView.View>
<GridView x:Name="gridView2">
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Visibility" Value="Collapsed" />
</Style>
</GridView.ColumnHeaderContainerStyle>
<GridViewColumn CellTemplateSelector="{StaticResource fixSideViewLogItemTemplateSelector}"/>
</GridView>
</ListView.View>
</ListView>
</ScrollViewer>
</DockPanel>
fixSideViewLogItemTemplateSelector and fixSideViewLogItemStyleSelector are the selectors, that return different datatypes or styles for each of the type in LogItems. The common datatype is a grid with two columns, but that also seems irrelevent - I tried to put a textbox there, and it still gets truncated.
I would like this column to be stretched to the whole gridView. When I set width, of the column, I see the column resizing, but I want it to occupy the whole space. This should be elastic - if I put one control in the window, it should occupy the whole window, and properly resize (with it's column) when the window is resized. If I put two controls, they should divide the space by halves, and still should be resized when the window is resized.
Any help, tips?
Upd
Here is an example of the template I'm using.
<DataTemplate x:Key="testCaseDataResultTemplate">
<!-- Test case results -->
<Grid Margin="50,0,0,0" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<!--Test case result property-->
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<!--Is retry / Name-->
<RowDefinition />
<!--Test case number-->
<RowDefinition />
<!--Low limit-->
<RowDefinition />
<!--High limit-->
<RowDefinition />
<!--Measured-->
<RowDefinition />
<!--State-->
<RowDefinition />
<!--Test time-->
<RowDefinition />
<!--Comment-->
</Grid.RowDefinitions>
<!--Is retry / Name-->
<Image Grid.Column="0" Grid.Row="0"
Source="..\Resources\retry16.png"
Stretch="None" HorizontalAlignment="Left"
Visibility="{Binding Path=IsRetry, Converter={StaticResource boolToVisibilityConverter}}" />
<TextBlock Text="fh fhgfhg fhfhfhgfhg fhgfhfhgfhgfhgfhgfhgfhgf hgfhgfhgfhgfhgfhg fhfhgfhgf hgfhgfhfhg fhfhgf rdederserswerv 2" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" TextWrapping="Wrap" MaxWidth="{Binding ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}}"/>
<!--Test case number-->
<TextBlock Text="Number:" Grid.Column="0" Grid.Row="1" />
<TextBlock Text="{Binding Path=TestCaseNumber}" Grid.Column="1" Grid.Row="1" />
<!--Low limit-->
<TextBlock Text="Low limit:" Grid.Column="0" Grid.Row="2" />
<TextBlock Text="{Binding Path=TestCaseData.LimitData.LowLimit}" Grid.Column="1" Grid.Row="2" />
<!--High limit-->
<TextBlock Text="High limit: " Grid.Column="0" Grid.Row="3" />
<TextBlock Text="{Binding Path=TestCaseData.LimitData.HighLimit}" Grid.Column="1" Grid.Row="3" />
<!--Measured-->
<TextBlock Text="Measured" Grid.Column="0" Grid.Row="4" />
<TextBlock Text="{Binding Path=MeasuredValue, Converter={StaticResource valasaConverter}}" Grid.Column="1" Grid.Row="4" />
<!--State-->
<TextBlock Text="Passed: " Grid.Column="0" Grid.Row="5" />
<TextBlock Text="{Binding Path=Passed}" Grid.Column="1" Grid.Row="5" />
<!--Test time-->
<TextBlock Text="Test time: " Grid.Column="0" Grid.Row="6" />
<TextBlock Text="{Binding Path=TestTime, StringFormat={}{0:hh':'mm':'ss'.'ff}}" Grid.Column="1" Grid.Row="6" />
<!--Comment-->
<TextBlock Text="{Binding Path=ShortMessage}"
Grid.Column="0" Grid.Row="7" Grid.ColumnSpan="2"
Visibility="{Binding Path=HasComment, Converter={StaticResource boolToVisibilityColConverter}}"
VerticalAlignment="Stretch"
MaxWidth="400"
TextAlignment="Center">
<TextBlock.ToolTip>
<StackPanel>
<TextBlock Text="{Binding Path=FullMessage}"/>
</StackPanel>
</TextBlock.ToolTip>
</TextBlock>
</Grid>
</DataTemplate>
It's a bit messy, but it is very simple. It has two columns - the captions, and the values. These columns are nothing to do with truncation.
I have tried also this template:
<DataTemplate x:Key="testCaseDataResultTemplate">
<TextBlock Text="Long long text goes here...... ->" HorizontalAlignment="Stretch"/>
</DataTemplate>
The text was of course longer :) It was still truncating, so I blame the listView/GridView, but not the inner template.
I think that this issue maybe is that you need to set the ListView.HorizontalContentAlignment to Stretch. Also the item container style and the item template must have the HorizontalAlignment to Stretch and the Width property must be Auto. Hope this tips helps...
EDIT
Also I think the problem could be the width of the GridViewColumn, that fix the items width
to it's own width. If you are using a single column, maybe you can change the ListView to a ListBox or an ItemsControl, just an idea.
I don't know what your templates looks like but I see a problem like this, it normally lies with a TextBlock that isn't wrapping and/or that the TextBlock's width is longer than it's parent.
Cannot say that I solved the puzzle, but at least it works as I expected. I removed the whole definition with GridView and columns inside, and put ItemTemplateSelector directly in ListView.
So my ListView looks now like this:
<ListView DockPanel.Dock="Top" Name="testCaseResultListView"
ItemsSource="{Binding LogItems}"
ItemContainerStyleSelector="{StaticResource fixSideViewLogItemStyleSelector}"
SelectionMode="Single"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
ItemTemplateSelector="{StaticResource fixSideViewLogItemTemplateSelector}">
That did it! Hope that will help to somebody as well.
I have a ListBox control that has been assigned to Grid.Column 0 which has a value of '*' defined for it's width, however when rendered there is a sizeable amount of space that is not being used.
I have also noticed that there is a border of sorts around the ListBox control itself, however I have not added one within the markup.
My UI (Areas of concern marked in Red):
My Markup:
<Window.Resources>
<DataTemplate x:Key="GameImagesTemplate" >
<StackPanel Orientation="Vertical">
<Image Source="{Binding FileInfo.FullName}" Margin="8,8,8,8" Height="70" Width="70" />
<Label Content="{Binding Name}" Width="70" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="GameTemplate">
<StackPanel>
<Label Content="{Binding Name}" Background="Gray" FontSize="16" />
<ListBox x:Name="imageContent" ItemsSource="{Binding FileList}" ItemTemplate="{StaticResource GameImagesTemplate}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ListBox x:Name="ContentList" ItemTemplate="{StaticResource GameTemplate}" Grid.Column="0" ScrollViewer.HorizontalScrollBarVisibility="Disabled" />
<StackPanel Grid.Column="1" Background="DarkGray">
<Button Click="OnLoad">_Load</Button>
<Button Click="OnSave">_Save</Button>
<Button Click="OnAdd">_Add</Button>
<Button Click="OnDelete">_Delete</Button>
</StackPanel>
</Grid>
How would I go about resolving both of the issues raised. Is it the default behaviour of the ListBox control?
Many thanks
Yes, that is the default behavior.
In the case of the alignment it looks like you have a WrapPanel in each ListBoxItem which doesn't have quite enough space to put another item on line 1. The remaining space is unused because of the HorizontalContentAlignment setting on ListBox defaulting to Left. This setting is in turn bound to by the default ListBoxItem. Setting HorizontalContentAlignment="Stretch" on your ListBox should fix that.
The outer border comes from the default setting for BorderBrush and BorderThickness. Setting BorderThickness="0" will get rid of it entirely.
There are some other default Padding settings that add some spacing in the default Styles and Templates. If you want to get more into those add a ListBox to a project in Blend and make a copy of its default Template and ItemContainerStyle and check out the XAML. Also consider using the base ItemsControl in cases where you don't need selection behavior, as it doesn't have any of these type of default settings.
I'd like to create a table on WP7. This is my current approach using a ListBox with a Grid as the data template.
<ListBox x:Name="ResultsList" Margin="12,0" Grid.Row="1">
<ListBox.Resources>
<DataTemplate x:Key="ResultsListItem">
<Grid d:DesignWidth="385" Height="28">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="88"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="textBlock1" Margin="0,0,24,0"/>
<TextBlock x:Name="textBlock2" Margin="0,0,24,0"
VerticalAlignment="Top" Grid.Column="1"/>
<TextBlock x:Name="textBlock3" Margin="0,0,24,0"
VerticalAlignment="Top" Grid.Column="3"/>
</Grid>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemTemplate>
<StaticResource ResourceKey="ResultsListItem"/>
</ListBox.ItemTemplate>
</ListBox>
The problem is, that the resulting table's columns are not sized equally. The Grid's column definitions are applied to each row independently of the other rows. That means, if there is a long text in textBlock1, column 0 will be larger. In the next row there could be a shorter text in textBlock1, resulting in column 0 also being shorter than the column 0 in the previous row.
How can the columns in all rows be sized equally? I don't want to use fixed width because when the orientation changes from portrait to landscape the colums would resize automatically.
There is the HeaderedItemsControl, but as I understand it it is not available for Windows Phone 7?
This is a tricky problem! In WPF there exists the concept of a SharedSizeGroup, which allows you to share column widths across multiple grids, but this is not available in silverlight.
There are a few workarounds on the web:
http://www.scottlogic.co.uk/blog/colin/2010/11/using-a-grid-as-the-panel-for-an-itemscontrol/
http://databaseconsultinggroup.com/blog/2009/05/simulating_sharedsizegroup_in.html
Although neither are simple solutions.
You might also try Mike's AutoGrid:
http://whydoidoit.com/2010/10/06/automatic-grid-layout-for-silverlight/
Here is my solution using SharedSizeGroup as suggested by ColinE.
<ListBox x:Name="ResultsList">
<ListBox.Resources>
<SharedSize:SharedSizeGroup x:Key="Col1Width" />
<SharedSize:SharedSizeGroup x:Key="Col2Width" />
<SharedSize:SharedSizeGroup x:Key="Col3Width" />
<DataTemplate x:Key="ResultsListItem">
<StackPanel d:DesignWidth="385" Orientation="Horizontal">
<SharedSize:SharedSizePanel WidthGroup="{StaticResource Col1Width}">
<TextBlock x:Name="textBlock" MaxWidth="100" Text="{Binding A}"/>
</SharedSize:SharedSizePanel>
<SharedSize:SharedSizePanel WidthGroup="{StaticResource Col2Width}">
<TextBlock x:Name="textBlock1" MaxWidth="85" Text="{Binding B}"/>
</SharedSize:SharedSizePanel>
<SharedSize:SharedSizePanel WidthGroup="{StaticResource Col3Width}">
<TextBlock x:Name="textBlock2" MaxWidth="200" Text="{Binding C}"/>
</SharedSize:SharedSizePanel>
</StackPanel>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemTemplate>
<StaticResource ResourceKey="ResultsListItem"/>
</ListBox.ItemTemplate>
</ListBox>
Even the maximum with of each column can be controlled via the TextBlock's MaxWidth property. The SharedSizeGroups ensure that the TextBlocks have the same size in each row.
You can use WrapPanel. Set the following ItemsPanel in the Datatemple, you can just have textblock.
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<control:WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>