full-sized image in popup - image

I'm using ListBox with custom DataTemplate, in this DataTemplate I have two thumbnails, when user clicks on one of this images I need to display a popup with a full-sized image(something like lightbox in JavaScript). I tried to use the Popup control in the DataTemplate, but the popup is positioned to current element on ListBox, not centered in the screen, and I'm not able to make it modal. I also tried to use the Coding4Fun toolkit, but I can't find any documentation or do it without any help.
Here is code of listbox:
<ListBox MaxHeight="600" ItemsSource="{Binding Items}" x:Name="LooksList" u:ScrollViewerMonitor.AtEndCommand="{Binding FetchMoreDataCommand}" d:LayoutOverrides="GridBox" BorderThickness="0" Margin="0,0,0,62">
<ListBox.ItemTemplate>
<DataTemplate>
<views:LookListItem />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And views:LookListItem:
<Grid x:Name="LayoutRoot">
<StackPanel x:Name="MainPanel" Margin="0,53,0,0" Orientation="Horizontal">
<StackPanel x:Name="PhotosPanel" Margin="20,11,0,0" Width="198" Height="126" HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
<Border BorderThickness="3" BorderBrush="White" Margin="0" HorizontalAlignment="Left" Width="93" Height="126">
<Image Source="{Binding Photo1.Thumb}" VerticalAlignment="Center" Tap="Image_Tap" />
</Border>
<Border BorderThickness="3" BorderBrush="White" Margin="12,0,0,0" HorizontalAlignment="Right" Width="93" Height="126">
<Image Source="{Binding Photo2.Thumb}" VerticalAlignment="Center" />
</Border>
</StackPanel>
</StackPanel>
</Grid>
Photo1 and Photo2 should be clickable and after click it should be a popup.
Thanks in advance!

There are a few ways you can go about doing this. I'll show how you can do this with a little code behind.
In your xaml:
<Grid>
<ListBox ItemsSource="{Binding MyItems}" ItemTemplate="{Binding MyTemplate}"
SelectionChanged="ListBox_SelectionChanged"/>
<Popup x:Name="Popup">
<Grid>
<ToggleButton Content="X"
IsChecked="{Binding IsOpen, ElementName=Popup, Mode=TwoWay}"
HorizontalAlignment="Right" VerticalAlignment="Top"/>
<Image x:Name="PopupImage"/>
</Grid>
</Popup>
</Grid>
In your code behind:
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs args)
{
ListBox listBox = (ListBox)sender;
MyImageObject obj = (MyImageObject)listBox.SelectedItem;
ImagePopup.Source = MyImageObjct.LargeImageSource;
Popup.IsOpen = true;
// Unselect item so user can "reselect" it -- If you need item later, save it somewhere
listBox.SelectedItem = null;
}
// Handle the back key button to close the popup
protected override void OnBackKeyPress(CancelEventArgs e)
{
if(Popup.IsOpen)
{
Popup.IsOpen = false;
e.Cancel = true;
}
}
UPDATE BASED ON LATEST INFO
If you do not need your view in a separate UserControl (no logic, only placement of controls) you can still use the example, but instead of listening to the SelectionChanged event, listen to the Tap event of each Image.
<ListBox MaxHeight="600" ItemsSource="{Binding Items}" x:Name="LooksList"
BorderThickness="0" Margin="0,0,0,62">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="MainPanel" Margin="0,53,0,0" Orientation="Horizontal">
<StackPanel x:Name="PhotosPanel" Margin="20,11,0,0" Width="198" Height="126" HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
<Border BorderThickness="3" BorderBrush="White" Margin="0" HorizontalAlignment="Left" Width="93" Height="126">
<Image Source="{Binding Photo1.Thumb}" VerticalAlignment="Center" Tap="Image1_Tap" />
</Border>
<Border BorderThickness="3" BorderBrush="White" Margin="12,0,0,0" HorizontalAlignment="Right" Width="93" Height="126">
<Image Source="{Binding Photo2.Thumb}" VerticalAlignment="Center"
Tap="Image2_Tap" />
</Border>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
The event of for Tap events would look something like
private void Image1_Tap(object sender, GestureEventArgs gestureEventArgs)
{
MyImageObject obj = ((FrameworkElement)sender).DataContext as MyImageObject;
// This is the event for Image1 Thumb, so show the Image1 Large
ShowPopup(obj.Photo1.Large);
}
If you do need a separate UserControl
You could create an "ImageOverlay" view much like in my Custom MessageBox Post. In your LookListItem view subscribe to the tap event for both thumbs
<Grid x:Name="LayoutRoot">
<StackPanel x:Name="MainPanel" Margin="0,53,0,0" Orientation="Horizontal">
<StackPanel x:Name="PhotosPanel" Margin="20,11,0,0" Width="198" Height="126" HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
<Border BorderThickness="3" BorderBrush="White" Margin="0" HorizontalAlignment="Left" Width="93" Height="126">
<Image Source="{Binding Photo1.Thumb}" VerticalAlignment="Center" Tap="Thumb1_Tap" />
</Border>
<Border BorderThickness="3" BorderBrush="White" Margin="12,0,0,0" HorizontalAlignment="Right" Width="93" Height="126">
<Image Source="{Binding Photo2.Thumb}" VerticalAlignment="Center" Tap="Thumb2_Tap" />
</Border>
</StackPanel>
</StackPanel>
In the tap events show the ImageOverlay control
private void Thumb1_Tap(object sender, GestureEventArgs gestureEventArgs)
{
ShowOverlay(Photo1.Large);
}
private void Thumb2_Tap(object sender, GestureEventArgs gestureEventArgs)
{
ShowOverlay(Photo2.Large);
}
private void ShowOverlay(ImageSource source)
{
ImageOverlay overlay = new ImageOverlay();
overlay.ImageSource = source;
overlay.Show();
}

Related

MenuFlyout for Items in GridView in Windows 8.1 HubApp

I have Windows 8.1 Hub App that will eventually be released for tablets. I want to add MenuFlyout to GridView. So if I right click or hold then flyout will display. I've gone through several videos, tutorials etc. but none of them relates to GridView. Only for ListView on WindowsPhone. So none of them show how I should approach.
Is it possible? How I should deal with it?
HubSection
This is how my Hubsection with GridView looks like.
<HubSection x:Name="CalcButtons" x:Uid="calculator" Header="{Binding Res.calc2Header, Source={StaticResource SharedStrings}}">
<DataTemplate>
<GridView
ItemsSource="{Binding}"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Items In Group"
ItemTemplate="{StaticResource StandardCalcButton}"
SelectionMode="None"
IsItemClickEnabled="True" Margin="0,0,0,0" ItemClick="GridView_ItemClick">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</DataTemplate>
</HubSection>
StandardCalcButton
I've created MenuFlayout as resource in App.xaml and attached it to GridViewItem DataTemplate. So it looks like this.
<MenuFlyout x:Key="CalcFlyout">
<MenuFlyoutItem Text="Test1"/>
<MenuFlyoutItem Text="Test2"/>
</MenuFlyout>
<DataTemplate x:Key="StandardCalcButton" >
<Grid Height="180" Width="180" Margin="5,5,5,5" FlyoutBase.AttachedFlyout="{StaticResource CalcFlyout}" >
<Border Height="180" Background="{StaticResource AppYellow}">
<StackPanel Grid.Row="1" Margin="0,0,0,0">
<Image Source="{Binding ImagePath}" AutomationProperties.Name="{Binding Title}" Height="130" Width="180"/>
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" TextLineBounds="Tight" TextAlignment="Center"/>
<TextBlock Text="{Binding Subtitle}" Style="{StaticResource BodyTextBlockStyle}" TextWrapping="NoWrap" TextLineBounds="Tight" LineStackingStrategy="BlockLineHeight" TextTrimming="CharacterEllipsis" TextAlignment="Center" />
</StackPanel>
</Border>
</Grid>
</DataTemplate>
This is how I want to make Flyout to open in GridView_ItemClicked
private void GridView_ItemClick(object sender, ItemClickEventArgs e){
FrameworkElement senderElement = e.ClickedItem as FrameworkElement;
if (senderElement == null)
{
Debug.WriteLine("null");
return;
} else
{
FlyoutBase flyoutBase = FlyoutBase.GetAttachedFlyout(senderElement);
flyoutBase.ShowAt(senderElement);
}
}
''ClickedItem'' is object which I deliver in ''GridView.DataContext'' so there is no way that it will be castable to FrameworkElement.
Now I'm stuck. I'll be thankful for any guidance.
You can try the following:
private void GridView_ItemClick(object sender, ItemClickEventArgs e)
{
var gridViewItemsControl = sender as ItemsControl;
var clickedItemContainer = gridViewItemsControl.ContainerFromItem(e.ClickedItem);
Debug.WriteLine(clickedItemContainer);
var clickedGridViewItem = clickedItemContainer as GridViewItem;
var clickedItemGrid = clickedGridViewItem.ContentTemplateRoot as Grid;
FlyoutBase flyoutBase = FlyoutBase.GetAttachedFlyout(clickedItemGrid);
flyoutBase.ShowAt(clickedItemGrid);
}
Hope i helps! :)

Getting information from child element of stackpanel within listbox

I know there should be a simple solution to this question but I just cant seem to figure it out here is what my code looks like:
<ListBox HorizontalAlignment="Left"
x:Name="locationsNB"
VerticalAlignment="Top"
Height="563"
Width="455"
SelectionChanged="locationsNB_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
Margin="18,0,0,0"
x:Name="placeDetails">
<Image Source="{Binding icon}"
Height="40"
Width="40"
VerticalAlignment="Top"
Margin="0,10,8,0" />
<StackPanel Width="350">
<TextBlock Text="{Binding name}"
FontSize="35"
Foreground="#399B81"
TextWrapping="Wrap" />
<TextBlock Text="{Binding vicinity}"
FontSize="20"
Foreground="#888888"
TextWrapping="Wrap" />
<TextBlock x:Name="reference"
Text="{Binding reference}"
Visibility="Collapsed" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I want to get the stackpanel->reference text (Text="{Binding reference}") of the selected item I dont know what my C# should look like but any help will be greatly appreciated.
If the ItemsSource of your ListBox is bound to a collection of items then you can use the SelectedItem property of the ListBox
private void locationsNB_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listbox = (ListBox)sender;
var myObject = listbox.SelectedItem as MyCustomObject;
if (myObject == null) return;
// perform your custom logic with this item
}

how to get listbox selected item value passing to another page for windows phone 7?

Hi am using xaml file given below.I want to get selected item value to details view.
<StackPanel Width="Auto">
<StackPanel VerticalAlignment="Top" Width="Auto">
<ListBox ItemsSource="{Binding Images}" Width="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" SelectionChanged="NotchsList11_SelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
</StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="White" Margin="0,0,8,0" BorderThickness="1">
<Image Source="{Binding}" Width="152" Height="90" Stretch="Fill" VerticalAlignment="Top"></Image>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" ScrollViewer.VerticalScrollBarVisibility="Disabled" Width="Auto">
<ListBox ItemsSource="{Binding Titles}" ScrollViewer.VerticalScrollBarVisibility="Disabled" SelectionChanged="NotchsList11_SelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal">
</StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate >
<Border BorderBrush="White" Margin="0,0,8,0"
BorderThickness="1">
<TextBlock Text="{Binding}" Width="152" Height="80" Padding="5,10,0,0" TextWrapping="Wrap"></TextBlock>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</StackPanel>
My Main.Cs Code
private void NotchsList11_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
NavigationService.Navigate(new Uri("/Test.xaml?parameter={0}",UriKind.Relative));
//NavigationService.Navigate(new Uri("/Page1.xaml?parameter=test", UriKind.Relative));
}
}
I used this thing i cant go to other page with selected item.
i want output like given below image
The simple and efficient approach - have a ViewModel. When the item is selected (hook the SelectionChanged event handler), pass the instance to the ViewModel and navigate to the second page that will show the item details. Make sure that the page is bound to the ViewModel and simply read from the item you passed in.

How to access listboxitem template data when an event of it's item control is fired?

I want to access each listboxitem template control's(image and 4 textblock controls )data when the button is clicked from the following hierarchy.
<ListBox x:Name="lstBoxNearbyPlaces" ItemsSource="{Binding Items}" Grid.Row="2" Margin="0,10,0,0" >
<ListBox.ItemTemplate>
<DataTemplate>
<Button Width="400" Height="150" Name="btnPlace" Click="btnPlace_Click_1">
<Button.Content>
<StackPanel Orientation="Horizontal" >
<Image Name="ImgPlace" Source="{Binding PlaceIconURL}" Width="50" />
<TextBlock Name="lblPlaceLat" Text="{Binding PlaceLatLocation}" Visibility="Collapsed"/>
<TextBlock Name="lblPlaceLng" Text="{Binding PlaceLongLocation}" Visibility="Collapsed"/>
<StackPanel Width="350" >
<TextBlock FontSize="20" Text="{Binding PlaceName}" Name="txtAddress" TextWrapping="Wrap" ></TextBlock>
<TextBlock FontSize="20" Text="{Binding PlaceVicinity}" Name="txtLocation" TextWrapping="Wrap"></TextBlock>
<Line MinHeight="5"></Line>
</StackPanel>
</StackPanel>
</Button.Content>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Is it possible to get or read the data of the every control here when the button click event is fired ?
You can get the binding object in the ListBox_SelectionChanged as the selected item.
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ItemModel model= listBox.SelectedItem as ItemModel ;
}
Or In the Buttonclick event you can get it as
private void Button_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
ItemModel model = button.DataContext as ItemModel;
}
Here model is the object which you have bind to that template.

Reloading listbox in WP7

I am using List to bind a listbox which is as follows:
<ListBox x:Name="ContentPanel" SelectionChanged="onSelectionChanged" Background="LightGray" Grid.Row="2">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Name="{Binding title}" Height="165" Margin="25,5,25,0" Width="430">
<Border BorderThickness="1" Height="165" BorderBrush="Gray">
<toolkit:ContextMenuService.ContextMenu >
<toolkit:ContextMenu IsZoomEnabled="False">
<toolkit:MenuItem Name="Delete" Header="Delete Message" Click="DeleteMessage_Click" >
</toolkit:MenuItem>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<StackPanel Orientation="Vertical">
<StackPanel>
<TextBlock Text="{Binding title}" Margin="5,0,0,0" FontSize="25" Foreground="Black"/>
<TextBlock Text="{Binding msgFrom}" Padding="5" TextWrapping="Wrap" Foreground="Gray" FontSize="20"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="5,13,0,0" FontSize="24" Foreground="WhiteSmoke" Text="{Binding msgReceivedOn}"/>
<toolkit:ToggleSwitch Margin="170,10,0,0" IsChecked="{Binding msgStatus}" Unchecked="UnChecked" Background="LightBlue" Checked="Checked"/>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
At first data is successfully loaded. But when I use the Contextmenu to remove the item and reload the listbox.. it fires an exception. Code to handle the context menu click is:
private void DeleteMessage_Click(object sender, RoutedEventArgs e)
{
MenuItem item = sender as MenuItem;
Message message = (Message)item.DataContext;
MessageBoxResult result = MessageBox.Show("Are you sure to delete the message??", "Confirmation", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.Cancel)
return;
else
{
ContentPanel.Items.Remove(message);
lstMessage.Remove(message);
}
ContentPanel.ItemSource = lstMessage;
}
But it this code is not working. So any suggestions?
You don't need each time to bind collection to a list. Also, when you remove an item from your collection, it should disappear also in the list (if binding setup properly). I think you have not ObservableCollection, so you need manage items manually. Please, consider to use ObservableCollection.
Your code should looks like:
lstMessage.Remove(message); //it must raises CollectionChanged event automatically
And this lines is unnecessary:
ContentPanel.Items.Remove(message);
ContentPanel.ItemSource = lstMessage;

Resources