ListBox and ApplicationBar: last element padding - xaml

I have a ListBox and ApplicationBar with Opacity=.5. I want that ListBox items are under the ApplicationBar.
Like figure:
But when I scrolled to end of list then last element of ListBox is under the ApplicationBar.
I want that last element is over ApplicationBar.
Can I add padding for a last element of the ListBox (LongListSelector)? How can solved this issue?
UPDATE
<ListBox Name="MyListBox">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<i:Interaction.Triggers>
<ec:DataTrigger Binding="{Binding RelativeSource=
{RelativeSource Self},
Converter={StaticResource IsLastItemInContainerConverter}}"
Value="True">
<ec:ChangePropertyAction PropertyName="Padding" Value="0,0,0,72"/>
</ec:DataTrigger>
</i:Interaction.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Background="Red"
Width="400"
Height="120"
Margin="15">
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
UPDATE 2
My problem can be easily solved by using LongListSelector. Just add empty ListFooterTemplate with Height = ApplicationBar height.

You can use converter to check if it's last item in listbox and in case yes, set padding to desired value via DataTrigger.
Check my answer over here for converter code. Just for sake of completeness of this answer i will post that converter code here:
public class IsLastItemInContainerConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
DependencyObject item = (DependencyObject)value;
ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(item);
return ic.ItemContainerGenerator.IndexFromContainer(item)
== ic.Items.Count - 1;
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
and use it like this:
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource=
{RelativeSource Self},
Converter={StaticResource IsLastItemInContainerConverter}}"
Value="True">
<Setter Property="Padding" Value="5"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>

edit: Didn't see the update to the original question. The below remains for additional detail.
This solution is for Windows Phone 8 only (although you could use the LongListSelector from the Windows Phone Toolkit if you are targeting 7.1/5).
I'd replace the ListBox with the LongListSelector from the SDK
<Grid>
<controls:LongListSelector ItemTemplate="{StaticResource Item}" ListFooterTemplate="{StaticResource Footer}" />
</Grid>
and for the templates add
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="Item">
<StackPanel Background="Red"
Width="400"
Height="120"
Margin="15">
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="Footer">
<Border Height="72" />
</DataTemplate>
</phone:PhoneApplicationPage.Resources>

Maybe simplest solution is to customize ItemsPanel property on ListBox:
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Margin="0,0,0,150"/> <!-- set margin to show some 'blank' space after last item -->
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
...
</ListBox>
But be aware that by default ListBox uses VirtualizedStackPanel as ItemsPanel. If you change it to StackPanel, it may bring some performance penalty. This is solution is suitable for lists with few items.

Related

Tooltip position in Oxyplot

I am recently using OxyPlot to draw charts for my WPF project. I have an issue with the tooltip in a line series. The rectangle box of the tooltip is too close to the point my mouse locates. I am wondering if there is any way to modify the position of the tooltip box and make it further from the cursor. Thank a lot. For example, I would like to move the tooltip box (in the red box) to right a bit.
[Edit]
Following Anu's idea, I added the following code but seems like it not works as expected.
In the xaml.cs file, I added
<UserControl.Resources>
<popups:ScreenPointToOffSetScreenPointConverter x:Key="ScreenPointToOffSetScreenPointConverter"/>
</UserControl.Resources>
And then change my OxyPlot to
<ItemsControl ItemsSource="{Binding AmplitudeDtos}" Margin="0" Name="Amplitude" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid popups:GridUtilities.ItemsPerRow="1" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type dtoModels:SignalDto}">
<oxy:PlotView Height="Auto" Width="Auto" MinHeight="40" MinWidth="100" HorizontalContentAlignment="Stretch"
FontStyle="Normal" FontFamily="Roboto, Microsoft YaHei" FontSize="8" Model="{Binding PlotModel}" Controller="{Binding PlotController}" Padding="8" Margin="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding SignalLoadedCommand}" CommandParameter="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<oxy:PlotView.DefaultTrackerTemplate>
<ControlTemplate>
<oxy:TrackerControl Position="{Binding Position, Converter={StaticResource ScreenPointToOffSetScreenPointConverter}}" LineExtents="{Binding PlotModel.PlotArea}">
<oxy:TrackerControl.Content>
<TextBlock Text="{Binding}" />
</oxy:TrackerControl.Content>
</oxy:TrackerControl>
</ControlTemplate>
</oxy:PlotView.DefaultTrackerTemplate>
</oxy:PlotView>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Please note that my OxyPlot is in a DataTemplate.
ScreenPointToOffSetScreenPointConverter class is the exactly the same as in Anu's example.
A relatively simple fix for the requirement would be to modify DefaultTrackerTemplate and use a Custom Converter to change the Position.For example, You could define a ScreenPoint converter as following
public class ScreenPointToOffSetScreenPointConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is ScreenPoint screenPoint)
{
return new ScreenPoint(screenPoint.X + 50, screenPoint.Y);
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// TODO: Implement
throw new NotImplementedException();
}
}
And then in your XAML
<oxy:PlotView Model="{Binding MyModel}">
<oxy:PlotView.DefaultTrackerTemplate>
<ControlTemplate>
<oxy:TrackerControl Position="{Binding Position,Converter={StaticResource ScreenPointToOffSetScreenPointConverter}}" LineExtents="{Binding PlotModel.PlotArea}">
<TextBlock Text="{Binding}" />
</oxy:TrackerControl>
</ControlTemplate>
</oxy:PlotView.DefaultTrackerTemplate>
</oxy:PlotView>
The Converter would add an Offset to the ScreenPoint position for the Tracker. You could modify the Offset Value to the Converter if it makes sense for your application requirement.

ListView ItemTemplate Grid 100% Width

I have made an ListView ItemTemplate and I want it to be responsive (when orientation changes, for example, the listView item changes in size). I am using a Grid as a control for the inner elements of the grid but it is not behaving. The ListView.ItemContainerStyle has property HorizontalAlignment="Stretch" which is the behaviour I want, and the ItemContainerStyle is the correct width. Inside the Border and Grid I have the same HorizontalAlignment="Stretch" and they are overflowing when the TextBox contained inside has lots of text, and when there is little or no text in the TextBox the Border element shrinks to be smaller than the ItemContainerStyle is showing.
<ListView ItemsSource="{Binding TileStories}" x:Name="cont" Margin="0,10,0,10" Background="{StaticResource CustomResourceBrush}" BorderBrush="{StaticResource CustomResourceBrush}" Foreground="{StaticResource CustomResourceBrush}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Margin" Value="20,10,20,10" />
<Setter Property="Foreground" Value="{StaticResource BTVioletBrush}" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Border CornerRadius="20" BorderThickness="0" Width="{Binding ScrollViewerWidth}" Background="White" HorizontalAlignment="Stretch">
<StackPanel Height="160" Orientation="Horizontal">
<Grid Background="black">
<TextBox Text="Example">
</Grid>
</StackPanel>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Just do this
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
Define MinHeight as 0 for ItemContainerStyle
Add to your ItemContainerStyle
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
And I think Width="{Binding ScrollViewerWidth}" is not required. You can remove this.
I didn't exactly find a solution but I did find a workaround. The Grid was being bound with Width="0" if I used {Binding ActualWidth, ElementName=StackPanel, Mode=OneWay} where StackPanel was the panel within the data template. I was poking around the designer in VS2013 and figured out that the Width was 0 because (I am assuming) the items in the data template are drawn one by one and therefore the Width was zero when the first template was drawn and so on and so forth. I haven't explained that very well I guess, but the important thing is the solution:
<PivotItem x:Name="Feed">
....
<Border CornerRadius="20" BorderThickness="0" Background="White" HorizontalAlignment="Stretch">
<StackPanel Height="160" Orientation="Horizontal">
<Grid HorizontalAlignment="Stretch" Width="{Binding ActualWidth, ElementName=Feed, Mode=OneWay}">
........
</Grid>
</StackPanel>
</Border>
...
</PivotItem>
I think that the PivotItem having a non-variable Width meant the Grid had a concrete Width to inherit from.

Unable to Bind ListView.SelectedItems.Count to Button.IsEnabled

I have a Button that I want to bind to the listview's selectedItem count. I cannot find where my error is. The button state is always enabled regardless of testListView.SelectedItems.Count.
Do I need a converter of some sort? If the Count is zero, it should implicitly convert that to a false no ?
<ListView x:Name="testListView" SelectionMode="Multiple" BorderThickness="1">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button x:Name="Button" Content="TestButton" IsEnabled="False" IsEnabled="{Binding ElementName=testListView, Path=SelectedItems.Count}"/>
Since the SelectedItems collection's Count property is of type int, and the IsEnabled property expects a bool input, and no implicit conversion of int to bool exists in C#, you'll need a converter or a data trigger.
A simple IValueConverter should do the trick, just use something like
return ((int)value) > 0;
as content of the Convert function!
Update using a DataTrigger via a Style; something like this should work:
<Button x:Name="Button" Content="TestButton">
<Button.Style>
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="true" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=testListView, Path=SelectedItems.Count}" Value="0">
<Setter Property="IsEnabled" Value="false" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>

Dynamically change a styled background color; XAML/VB in Visual Studio Express 2012 for Windows 8

In a DataTemplate in StandardStyles.xaml I have this StackPanel:
<DataTemplate x:Key="Standard160x160ItemTemplate">
<Grid HorizontalAlignment="Left" Width="160" Height="160">
...
<StackPanel
VerticalAlignment="Top"
Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
<TextBlock Text="{Binding UniqueID}"
Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}"
Style="{StaticResource TitleTextStyle}" Height="30" Margin="15,0,15,0"/>
</StackPanel>
...
</Grid>
</DataTemplate>
"uniqueID" is a property of a "Product" class:
Public NotInheritable Class Product
Private Property _sUID As String = String.Empty
Public Property UniqueID As String
Get
Return Me._sUID
End Get
Set(value As String)
Me.SetProperty(Me._sUID, value)
End Set
End Property
...
End Class
I use above template "Standard160x160ItemTemplate" in a grid view item like this:
<GridView Height="210"
x:Name="ItemView"
SelectionMode="None"
ItemsSource="{Binding Source={StaticResource itemsViewSource}}">
<GridViewItem
x:Name="GridViewItem"
ContentTemplate="{StaticResource Standard160x160ItemTemplate}"
Tapped="GridViewItem_Tapped">
<GridViewItem.Style>
<Style TargetType="FrameworkElement">
<Setter Property="Margin" Value="0,0,0,0"/>
</Style>
</GridViewItem.Style>
</GridViewItem>
</GridView>
This works well and does what it should.
However, in some cases (depending on two other properties of the "Product" object, specifically if one of them has a lower UInt value than the other) I want to change the StackPanel's background to a solid "Red" instead of "{StaticResource ListViewItemOverlayBackgroundThemeBrush}".
I don't doubt it is possible, but I am new to XAML (not to VB though) and am still overwhelmed by the thousands of XAML tags and am really struggling to find a solution.
So the question is: How can I dynamically change the template's background, based on the "Product" properties "A" and "B"?
The best way would probably be to use custom IValueConverter. Here's the example from MSDN.

Silverlight Listbox update style at runtime

I have a listbox control added to my layout as show in the below code snippet.
<ListBox x:Name="lstFilters" ItemsSource="{Binding CustomerCollection, Source={StaticResource VMCustomers}}" ScrollViewer.VerticalScrollBarVisibility="Disabled" Height="200" Margin="12,20,235,80">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<HyperlinkButton Content="{Binding Name}" Style="{StaticResource styleFont}"></HyperlinkButton>
<TextBlock x:Name="txtFilterCount" Text="{Binding ContactNumber, Mode=TwoWay}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Style x:Key="styleFont" TargetType="HyperlinkButton">
<Setter Property="FontFamily" Value="Verdana"></Setter>
</Style>
I have written a style that sets the font family to HyperlinkButton control.
Now i want to set this fontfamily from code behind because i am getting the value at runtime. so how to change it and one more thing i want to do this at the constructor or page load event i.e. i want to set this only once and it should apply for all the items i.e if there are 100 items then it should get applied to all the 100 items. so it makes it faster instead of always binding it any event.
The easiest way to do this is to bind the style to a property of the UserControl using the following XAML:
<Style x:Key="styleFont" TargetType="HyperlinkButton">
<Setter Property="FontFamily"
Value="{Binding DataContext.ListFont,
RelativeSource={RelativeSource AncestorType=UserControl}}">
</Setter>
</Style>
Then you just need to update the property and the style will reflect the new Font for all the list items.
Update:
This answer is only valid for Silverlight 5.