Button after ListBox - silverlight

I need to show ListBox with dynamic content (so I do not know its height) and Button below it. So user should be able to scroll ListBox to end and see button.
In Android I would use RelativeLayout and below property for button or some other solution, but in WP I do not know how to do it.
What I had tryed:
1) Put all in StackPanel
<StackPanel>
<ListBox />
<Button />
</StackPanel>
This is not working, because StackPanel is blocking ListBox scrolling.
2) Ok, lets put ListBox in Grid
<StackPanel>
<Grid>
<ListBox />
</Grid>
<Button />
</StackPanel>
Nothing happens.
3) Put all in Grid and use Grid.Row not worked.
4) Lets put all in Grid and set margin for Button dynamically
<Grid>
<ListBox />
<Button />
</Grid>
Ok, this is working, but it is not good solution , because I need to handle ListBoxpopulating each time and reset margin for button. Bad bad bad.
P.S. Also, I can put button as ListBox item (not bad, but not good :)
Help me please...

If I understood you correctly, you need a simple Grid defined like this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListBox />
<Button Grid.Row="1" Height="80"/>
</Grid>
By making height of the row zero to "star" and the first row to Auto, the ListBox will fill the remaining space, and the Button only 80 (you can change this to whatever you like). ListBox is automatically put to row zero because that's the default if it is not explicitly set.
If you don't want the button fixed on the page but to scroll with the ListBox, you could edit the ListBox template like this:
<Style x:Key="ListBoxWithButtonStyle" TargetType="ListBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ScrollViewer x:Name="ScrollViewer" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" Padding="{TemplateBinding Padding}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ItemsPresenter/>
<Button Content="Touch me" Height="80" Grid.Row="1"/>
</Grid>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And then apply to ListBox:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox Style="{StaticResource ListBoxWithButtonStyle}">
</ListBox>
</Grid>

Related

WPF Exceed busyindicator + listbox combination style issues

I am using xceed busyindicator control and listbox with the very simple example. So i have background color of listbox set to black and when isbusy property of busyindicator is set to true. Listbox background color changes to white but for the rest of the control like grids background color remains the same. See example below. I want my listbox color to remain same as what i set but its changes to white when isBusy =true.
<Grid Margin="10">
<xctk:BusyIndicator IsBusy="True">
<Grid Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="0.50*" />
<RowDefinition Height="0.50*" />
</Grid.RowDefinitions>
<ListBox Background="Black" Foreground="White">
<ListBoxItem>ListBox Item #1</ListBoxItem>
<ListBoxItem>ListBox Item #2</ListBoxItem>
<ListBoxItem>ListBox Item #3</ListBoxItem>
</ListBox>
</Grid>
</xctk:BusyIndicator>
</Grid>
The BusyIndicator has by default a semi-transparent Overlay. Also, it sets the underlying element's IsEnabled=False
You can achieve what you want like this:
<Grid Margin="10">
<Grid.Resources>
<Style x:Key="_BlackListBoxStyle" TargetType="{x:Type ListBox}">
<Setter Property="Background" Value="Black" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<Grid Width="Auto" Height="Auto">
<Border x:Name="Border" CornerRadius="0,0,0,0" />
<ScrollViewer
Focusable="false"
HorizontalScrollBarVisibility="Disabled"
IsTabStop="False"
>
<StackPanel IsItemsHost="true" />
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="BorderThickness" Value="0,0,0,0" />
</Style>
</Grid.Resources>
<xctk:BusyIndicator IsBusy="True">
<Grid Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="0.50*" />
<RowDefinition Height="0.50*" />
</Grid.RowDefinitions>
<ListBox IsEnabled="False" Style="{StaticResource _BlackListBoxStyle}">
<ListBoxItem>ListBox Item #1</ListBoxItem>
<ListBoxItem>ListBox Item #2</ListBoxItem>
<ListBoxItem>ListBox Item #3</ListBoxItem>
</ListBox>
</Grid>
<xctk:BusyIndicator.OverlayStyle>
<Style TargetType="Rectangle">
<Setter Property="Fill" Value="Transparent" />
</Style>
</xctk:BusyIndicator.OverlayStyle>
</xctk:BusyIndicator>
</Grid>

Add Text at the bottom of the last ListViewItem

I want to add a TextBox after the last item of a ListView (or at the bottom inside of the ItemsPresenter of a ListView).
At the moment I am defining a template for the last ListViewItem and I am using a converter to be sure which element is the last one.
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource LastItemInContainerConverter}}" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<StackPanel Orientation="Vertical">
<Border Name="Border" BorderBrush="#DCDCDC" Background="#eeeeec" BorderThickness="1" Margin="0,0,0,5">
<ContentPresenter />
</Border>
<TextBox>Hello!</TextBox>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
But the items are in a ObservableCollection and I am getting problems about the layout refreshing upon adding and removing items.
Any approach or idea how can I define that?
Ok, I find the solution.
<ListView.Template>
<ControlTemplate>
<Border>
<ScrollViewer>
<!-- this is needed -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<ItemsPresenter />
<TextBlock Grid.Row="1">Hello!!!</TextBlock>
</Grid>
</ScrollViewer>
</Border>
</ControlTemplate>
</ListView.Template>

Silverlight: Add Button Above a Column of Chart

I want to add a button above all column in Charts in the Silverlight Toolkit.
Same with this Picture:
I add style for DataPointStyle:
<Style x:Key="ColorByGradeColumn" TargetType="toolkit:ColumnDataPoint">
<Setter Property="Background" Value="DarkGray"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="toolkit:ColumnDataPoint">
<Border
MouseEnter="Border_MouseEnter"
MouseLeave="Border_MouseLeave"
Background="{Binding Legend.Color,
Converter={StaticResource stringToSolidColorBrushConverter}}"
BorderThickness="0.5"
Tag="{Binding Legend}"
MouseLeftButtonUp="Col_MouseLeftButtonUp">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
but i don't know where i should add button.
You can add anything you need to the ControlTemplate.
In your case this would mean you have to add a Panel (e.g. a Grid) to arrange the button and the bar:
<ControlTemplate TargetType="toolkit:ColumnDataPoint">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" ... />
<Border Grid.Row="1" ... />
</Grid>
</ControlTemplate>

ItemsControl is preventing item content from expanding to fill its container

I am creating a WPF custom control that inherits from ItemsControl. In the ControlTemplate of my control I have an ItemsPresenter. The problem is that I need to be able to get content in the items presenter to fill the entire content area. In the code below I have a simplified example of the broken code and also what I am trying to accomplish. BTW setting HorizontalAlignment and VerticalAlignment to Stretch causes the content expand horizontally but not vertically.
<Window x:Class="yada"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="768" Width="1024">
<Grid>
<Grid.Resources>
<Style TargetType="Border" x:Key="stepBorder">
<Setter Property="Background" Value="CadetBlue"></Setter>
<Setter Property="BorderBrush" Value="Green" ></Setter>
<Setter Property="BorderThickness" Value="2"></Setter>
<Setter Property="Padding" Value="25"></Setter>
</Style>
</Grid.Resources>
<TabControl Margin="0,20,0,0">
<TabItem Header="Broken">
<Border>
<ItemsControl>
<ItemsControl.Items>
<Control>
<Control.Template>
<ControlTemplate>
<Border Style="{StaticResource stepBorder}">
<TextBlock Text="Border fills small region near the top"></TextBlock>
</Border>
</ControlTemplate>
</Control.Template>
</Control>
</ItemsControl.Items>
</ItemsControl>
</Border>
</TabItem>
<TabItem Header="Works">
<Border>
<Control>
<Control.Template>
<ControlTemplate>
<Border Style="{StaticResource stepBorder}" >
<TextBlock Text="Border fills entire control"></TextBlock>
</Border>
</ControlTemplate>
</Control.Template>
</Control>
</Border>
</TabItem>
</TabControl>
</Grid>
</Window>
Here is some code from my control. I cant include it all, there is too much. I think this is the relevant part however:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Wizard}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" x:Name="ContentRow" />
<RowDefinition Height="{Binding ElementName= NavButtonPanel,Path=ActualHeight}"></RowDefinition>
</Grid.RowDefinitions>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" x:Name="ContentScrollViewer" MaxHeight="{Binding ElementName=ContentRowHeight, Path=ActualHeight}">
<ItemsPresenter
x:Name="Presenter"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">
</ItemsPresenter>
</ScrollViewer>
<Border Style="{TemplateBinding NavButtonPanelStyle}" Grid.Row="1" x:Name="NavButtonPanel">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
</StackPanel>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate></DataTemplate>
</Setter.Value>
</Setter>
As usual, just posting on SO gets me halfway to my answer.
It turns out the ItemsControl is using an evil stackpanel as a container for items. Fortunately there is a top-secret property called ItemsPanel that lets you change this. Just set it to a grid as shown below and you are in business.
In my case I am writing a custom control that inherits from ItemsControl so in the Style I add this property setter:
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Grid></Grid>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>

Silverlight: Difficulty with ScrollViewer

I'm making a wp7 Silverlight app. I have a ScrollViewer that contains a ListBox of ten elements. However, it only lets me scroll down a tiny bit. What could I be doing wrong?
<ScrollViewer>
<ListBox x:Name="StoryListBox"/>
</ScrollViewer>
The ListBox is filled with items of the following type:
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image x:Name="Thumbnail" Grid.Column="0" Width="89" HorizontalAlignment="Left" VerticalAlignment="Top" />
<TextBlock x:Name="Headline" Grid.Column="1" Grid.Row="0" Style="{StaticResource PhoneTextAccentStyle}" TextWrapping="Wrap" HorizontalAlignment="Left" Width="299" FontSize="23.333" VerticalAlignment="Top" />
<TextBlock x:Name="Teaser" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1" HorizontalAlignment="Left" Style="{StaticResource PhoneTextSubtleStyle}" TextWrapping="Wrap" VerticalAlignment="Top" Width="384"/>
</Grid>
What could I be doing wrong here?
I do not see the reason why you would need the ListBox to be embedded within the ScrollViewer. If your ListBox has more items than it display in the viewable area, the ListBox items should scroll by themselves. If you edit the ListBox's style using Expression Blend, the style will look like this -
<Style x:Key="ListBoxListStyle" TargetType="ListBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ScrollViewer
x:Name="ScrollViewer"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Foreground="{TemplateBinding Foreground}"
Padding="{TemplateBinding Padding}" >
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You can see the ScrollViewer embedded in the ControlTemplate of the ListBox, it takes care of the scrolling of ListBoxItems.
It(Scrolling) is working perfectly after I set the Height of the list box.
The ScrollViewer could ONLY work when it is smaller than which it contains (either width or height). If you do not indict the width or height of the ScrollViewer, it will be stretched to fit its content, and as a result the effect would not be perfect.
So what you need to do is to set a fixed size for your ScrollViewer.
By the way, as indyfromoz said, a ListBox already has a ScrollViewer, so you could remove your outer ScrollViewer, and just set the ListBox's size.

Resources