Display Border around Selected Item in ListBox - c#

I am a ListBox with images from IsolatedStorage, in which the user may select an image to use. I would like to somehow show the user which image they have currently selected, or pressed, within the Listbox via a border around the image (or another way if better). I am not sure exactly how to get the currently selected image and place a border around that image. I am currently using the SelectionChanged event of the ListBox to attempt this functionality. What I have so far is as follows:
MainPage.xaml
<ListBox x:Name="Recent" ItemsSource="{Binding Pictures}" Margin="8"
SelectionChanged="recent_SelectionChanged" toolkit:TiltEffect.IsTiltEnabled="True">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Image x:Name="recentImage" Source="{Binding Source}" Margin="12" Width="115"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
MainPage.xaml.cs
private void recent_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//Place border round currently selected image
//?
}
Any thoughts?

Update to Fix
MainPage.xaml
//within the ListBox DataTemplate
<Border>
<Image x:Name="recentImage" Source="{Binding Source}" Margin="12" Width="115"/>
</Border>
MainPage.xaml.cs
//within recent_SelectionChanged
var lb = sender as ListBox;
var lbi = lb.ItemContainerGenerator.ContainerFromItem(lb.SelectedItem) as ListBoxItem;
lbi.BorderThickness = new Thickness(2, 2, 2, 2);
lbi.BorderBrush = new SolidColorBrush((Color)Application.Current.Resources["PhoneAccentColor"]);

I'd create another image on top of the image in your data template. This image would be mostly transparent with just the border and maybe a little tick (like Windows 8 apps have). Then I would toggle the visibility of this image when the item is selected.
Because the image would be mostly transparent it would show as a border around the selected image.
I use this technique to 'grey out' items (by using a solid black image with ~10% opacity) and it works really well.
You should be able to simply bind the visibility to the selected property - though you'd need a converter to convert between boolean and visibility.
<DataTemplate>
<Image x:Name="recentImage" Source="{Binding Source}" Margin="12" Width="115"/>
<Image x:Name="borderImage" Source="Images/borderimg.png" Margin="12" Width="115" Visibility="Collapsed"/>
</DataTemplate>
Then:
private void recent_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//set the visibility property of the selected item to 'Visible'
}

Related

Handle SwapChainPanel in ListView

I have my xaml code
<ListView x:Name="ListVideo"
ItemsSource="{x:Bind ScreenList}"
VerticalAlignment="Stretch"
FlowDirection="LeftToRight"
Grid.Row="1"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ScrollViewer.HorizontalScrollBarVisibility="Hidden">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<controls:UniformGrid></controls:UniformGrid>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Background="White"
BorderBrush="White"
BorderThickness="1">
<SwapChainPanel x:Name="swapChain"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate></ListView>
with ScreenList is type of ObservableCollection. So the question is how can I add new SwapChainPanel in the ListView?.
I intend to add SwapChainPanel item, and with each item I use DirectX to render video, so i want to get the object SwapChainPanel item in code-behind to process then.
Thanks.
So the question is how can I add new SwapChainPanel in the ListView
You have placed SwapChainPanel in the Listview DataTemplate, and current listview ItemsSource is ObservableCollection. So you just need add new item into ObservableCollection, the listview will render new item automatically.
so i want to get the object SwapChainPanel item in code-behind
You could get itemContainer with ContainerFromItem method, and find swapChain with name in ContentTemplateRoot.
var container = MyList.ContainerFromItem(MyList.Items[0]) as ListViewItem;
var swapChain = (container.ContentTemplateRoot as Grid).FindName("swapChain");
Update
As the Hoka Biu comment below, you could also get swapChain instance within SwapChainPanel Loaded event.
<SwapChainPanel Loaded="swapChain_Loaded"/>
private void swapChain_Loaded(object sender, RoutedEventArgs e)
{
var swapChain = sender as SwapChainPanel;
}

List of horizontal ScrollViewer - WP8

Im trying to achive this on a windows phone 8 project:
I want to have a number of rows filled with elements (images in this case) that i can scroll in the horizontal, having the ability to click on them and navigate to a new page, besides that, i want that list to be scrollable on the vertical
For example, i would scroll down til i saw Row 10, then on Row 10 i wouls scroll to the right until i get to the image 8, and when i pressed it i would navigate to another page.
if anyone could give me a clue on how to make this happen i would appreciate
Maybe this will help you. Put a Scrollviewer inside a ListBox Datatemplate with Horizontal scrollBarVisibility.
<ListBox Grid.Row="1" Name="listBoxClient">
<ListBox.ItemTemplate>
<DataTemplate>
<ScrollViewer VerticalAlignment="Top" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled" Width ="400">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding YourImageSource}" Width="YourWidth" Height="YourHeight" Tap="Iamge_Tap"/>
</StackPanel>
</ScrollViewer>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In code behind
private void Iamge_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
NavigationService.Navigate(new Uri("Your page path",UriKind.Relative));
}

How do I get access to the item in a ListBox that is being rendered rather than its source data?

In a continuation from my question here
I tried using the solution provided in the linked answer, however when I give it the image which the ListBox is binding to, it gives me the wrong position, because the Item Template is loading in a source URL rather than the actual image, and it seems the data is null.
My Item Template looks like this:
<ListBox ItemsSource="{Binding Items}"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
Height="64" Name="listBoxSource"
VerticalAlignment="Bottom"
SelectionChanged="listBoxSource_SelectionChanged" Canvas.Left="32" Canvas.Top="365" Width="596"
>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image x:Name="ListImage" Source="{Binding thumbnailURL}" Height="64" Width="64"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
How do I get access to "ListImage" for the currently selected Item?
Every ItemsControl has an ItemsContainerGenerator, which (surprisingly enough) is responsible for generating a control for each item in the list. It provides a few useful methods for finding the container of a given item, and vice versa. You can use it like this:
private void listBoxSource_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listBox = (ListBox) sender;
var containerGenerator = listBox.ItemContainerGenerator;
var container = (UIElement)containerGenerator.ContainerFromItem(listBox.SelectedItem);
}
You can then use the variable container with the solution from your other post to find the coordinates,
Point position = container.GetRelativePosition(Application.Current.RootVisual);
And on a side note, in your DataTemplate you don't need the StackPanel, since the ListBox is providing that with its ItemsPanelTemplate.
<DataTemplate>
<Image x:Name="ListImage" Source="{Binding thumbnailURL}" Height="64" Width="64"/>
</DataTemplate>
on tap event you can do this:
private void image_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
Image selectedImage = e.OriginalSource as Image;
}
is this what you need?
I would suggest a different solution because the way you are trying to solve it (finding the control) is prone to error.
Make the DataTemplate a resource and refer to it in the ListBox by using ItemTemplate="{StaticResource myTemplate}"
Next, when an item is selected, add a ContentControl to the Canvas, set its ContentTemplate to the same DataTemplate and the DataContext to the SelectedItem.
This way you only have to define the template once (one place to maintain it) and do not have to walk the VisualTree.

Scrollviewer Problem wpf

I am displaying images inside the listbox. i have placed this listbox inside the scrollviewer. I am using two repeat button to move the listbox items. I am binding the listbox using datacontext.
Problem:
If i move the images using the button and click on the image in the lisbox it moves to the initial position.
Code:
<RepeatButton Click="rbtnLeft_Click" Name="rbtnLeft" Width="30" Height="30">
<Image Source="Images/GeneralImages/search_right_arrow.jpg"></Image>
</RepeatButton>
<Grid x:Name="grid" Width="666" HorizontalAlignment="Left">
<ScrollViewer Grid.Row="1" Name="svGame"
VerticalScrollBarVisibility="Hidden"
HorizontalScrollBarVisibility="Hidden" >
<ListBox ClipToBounds="True" Name="lbGameImage" Width="Auto" SelectionChanged="lbGameImage_SelectionChanged" ItemsSource="{Binding}" ItemsPanel="{DynamicResource iptListBox}" ItemContainerStyle="{DynamicResource ListBoxItemStyle}"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"/>
</ScrollViewer>
</Grid>
<RepeatButton Click="rbtnRight_Click" Name="rbtnRight" Width="30" Height="30">
<Image Source="Images/GeneralImages/search_left_arrow.jpg"></Image>
</RepeatButton>
c# Code:
private void rbtnLeft_Click(object sender, RoutedEventArgs e)
{
svGame.ScrollToHorizontalOffset(svGame.HorizontalOffset + 5);
}
private void rbtnRight_Click(object sender, RoutedEventArgs e)
{
svGame.ScrollToHorizontalOffset(svGame.HorizontalOffset - 5);
}
The problem is that the ListBox thinks it owns the ScrollViewer, so whenever the selection changes it sets the offset back to what it wants. Set ScrollViewer.CanContentScroll="False" in the ListBox to prevent this.
You need to turn off the internal ScrollViewer inside the ListBox. You could do it by re-templating lbGameImage to remove the ScrollViewer completely but the quicker way (which it looks like you tried to do) is to set both of the ScrollBarVisibility settings on lbGameImage to "Disabled". Hidden means that they're still active and scrolling the content, you just can't see them.

How to Set focus on the 1st Item of Nested Listbox in Silverlight?

I have a List box which contains another lisbox Inside it.
<ListBox x:Name="listBoxParent">
<ListBox.ItemTemplate>
<DataTemplate>
<Image x:Name="thumbNailImagePath" Source="/this.jpg" Style="{StaticResource ThumbNailPreview}" />
<TextBlock Margin="5" Text="{Binding Smthing}" Style="{StaticResource TitleBlock_Artist}" />
</StackPanel>
<StackPanel Style="{StaticResource someStyle}" >
<ListBox x:Name="listBoxChild" Loaded="listBoxChild_Loaded" BorderThickness="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Margin="5" Text="{Binding myText}" Width="300"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
</ListBox.ItemsPanel>
</ListBox>
Now while I try to focus to the 1st item of the child List Box It focus repeteadly(as it get repeated inside parent Listbox) on 1st all the 1st items of parentlistbox, wish I could have provide a Screen shot for Better Understanding. But Can't
public void listBoxChild_Loaded(object sender, RoutedEventArgs e)
{
var myListBox = (ListBox)sender;
myListBox .ItemsSource = PageVariables.eOUTData;//listboxSongsData;
myListBox .SelectedIndex = 0;
myListBox .Focus();
}
Thanks,
Subhen
It's difficult to determine what you're trying to accomplish in your code.
One idea:
Have you considered changing the inner ListBox to an ItemsControl? If you needed it to scroll as well, you could layer it in a ScrollViewer.
Second idea (possibly an additional idea):
Every item that created in the item template is calling the Loaded event. Don't you want that to happen only once? Remove the event from the inner ListBox and set focus once the outer list has been loaded.

Categories