ContextMenu, get Parent TextBlock Id - windows-phone-8

ItemSource for the ListBox is a ObservableCollection of Animals.
Each animal have a Name and a Id. Inside the TextBlock showing the name of the animal, I have a ContextMenu. When long tap, it shows a menu UnFollow. When clicking on that Menu it raises the UnFollow_OnClick event.
Now to my question, how can I in my code behind get the Id of the animal?
Have tried some different scenarios but cannot find any working solutions.
<ListBox x:Name="AllAnimals" Margin="0,0,-12,0" ItemsSource="{Binding AllAnimals}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17">
<TextBlock Text="{Binding Name}" TextWrapping="NoWrap" Style="{StaticResource PhoneTextExtraLargeStyle}">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu IsZoomEnabled="False">
<toolkit:MenuItem Header="Unfollow" Click="UnFollow_OnClick" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
private void UnFollow_OnClick(object sender, RoutedEventArgs e)
{
}

this should work:
private void UnFollow_OnClick(object sender, RoutedEventArgs e)
{
Animal animal = ((Animal)((sender as FrameworkElement).DataContext));
MenuItem item = (sender as MenuItem);
string itemValue = item.Header.ToString();
if (itemValue == "Unfollow")
{
try
{
if (animal != null)
{
// animal.Id
}
}
catch (Exception)
{
}
}
}

Try this:
private void UnFollow_OnClick(object sender, RoutedEventArgs e)
{
var animal = AllAnimals.SelectedItem as Animal;
if(animal==null) return;
var id = animal.Id;
}
Hope its help.

Related

How to popup ContextMenu in ListBox programmatically on Windows Phone?

I have a ListBox in my page, I want some items in the ListBox can popup ContextMenu when you long press it, and some items don't, how can I implement this requriment programmatically?
Here is one possible solution. Define your Item's class with some information about popup:
public class Item
{
public string Info { get; set; }
// Menu attached or not
public bool OptionsEnabled { get; set; }
}
In XAML you will have to define your ListView (or ListBox) with apropriate ItemTelplate:
<ListView Name="myList" Holding="myList_Holding">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Info}" FontSize="24" Margin="7">
<FlyoutBase.AttachedFlyout>
<MenuFlyout>
<MenuFlyoutItem Text="First option"/>
<MenuFlyoutItem Text="Second option"/>
</MenuFlyout>
</FlyoutBase.AttachedFlyout>
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Then upon Holding event you can check OptionsEnabled property if to show a menu,if yes then do so:
private void myList_Holding(object sender, HoldingRoutedEventArgs e)
{
if (e.OriginalSource == null || !(e.OriginalSource is TextBlock)) return;
TextBlock listItem = e.OriginalSource as TextBlock;
if (listItem.DataContext == null) return;
Item itemData = listItem.DataContext as Item;
if (itemData.OptionsEnabled)
FlyoutBase.ShowAttachedFlyout(listItem);
}
A working sample you can download here.

Using FlipView to create TabControl in Metro Apps

i'm currently creating a Metro Style Application and want to use the FlipView control to work like the tab control in WPF and winforms, please can any one help me ?
You would put FlipViewItems in the FlipView the same way you'd put TabItems in a TabControl. To add tabs - you could have a StackPanel with TextRadioButtonStyled RadioButtons that have their check states synchronized with the FlipView selection state. Alternatively you could have a heavily styled ListView for the headers bar.
i solved it by editing the flipviewitem template and making its view like the wanted tab page view. Then i added a button on the top of every item to activate it.
We don't have Tab Control in WP8.1 but we can customize using FlipView. Flip View has a property selected index so we can set which view we want.
Create a xaml page, for example MainPage.xaml
For Tab Header
<Border BorderThickness="0,0,0,1" BorderBrush="White" >
<Grid Grid.Row="0" Background="Black" x:Name="navigateHead" >
<TextBlock x:Name="appbarSports" Text="Sports" Tapped="appbarSports_Tapped" TextAlignment="Center" Width="80" Margin="0,34,320,7" />
<TextBlock x:Name="appbarCars" Text="Cars" Tapped="appbarCars_Tapped" Margin="160,34,160,7" TextAlignment="Center" />
<TextBlock x:Name="appbarHomes" Text="Homes" Tapped="appbarHomes_Tapped" Margin="80,34,240,7" TextAlignment="Center" />
<Image x:Name="imgLine0" Source="ms-appx:///Images/white.png" Width="80" Height="3" Stretch="Fill" Margin="0,55,320,1" ></Image>
<Image x:Name="imgLine1" Source="ms-appx:///Images/white.png" Width="80" Height="3" Stretch="Fill" Margin="81,55,239,1" Visibility="Collapsed" />
<Image x:Name="imgLine2" Source="ms-appx:///Images/white.png" Width="80" Height="3" Stretch="Fill" Margin="162,55,158,1" Visibility="Collapsed" />
</Grid>
</Border>
For Flip view XAML code is
<Grid Grid.Row="1" >
<FlipView x:Name="flipControl" SelectionChanged="flipControl_SelectionChanged" >
<FlipViewItem >
<ListView x:Name="listViewForSports" >
<ListView.ItemTemplate>
<DataTemplate>
<Image Stretch="Fill" Source="{Binding SportsImage}"></Image>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</FlipViewItem>
<FlipViewItem >
<ListView x:Name="listViewForHomes">
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding HomesImage}" Stretch="Fill"></Image>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</FlipViewItem>
<FlipViewItem >
<ListView x:Name="listViewForCars">
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding CarsImage}" Stretch="Fill"></Image>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</FlipViewItem>
</FlipView>
</Grid>`
and write in code behind file MainPage.xaml.cs
Just initialize these globally:
public sealed partial class MainPage : Page
{
List<Sports> listOfSports;
List<Cars> listOfCars;
List<Homes> listOfHomes;
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
bind data to the FlipView control when page is initialized
protected override void OnNavigatedTo(NavigationEventArgs e)
{
flipControl.SelectedIndex = 0;
// TODO: Prepare page for display here.
// TODO: If your application contains multiple pages, ensure that you are
// handling the hardware Back button by registering for the
// Windows.Phone.UI.Input.HardwareButtons.BackPressed event.
// If you are using the NavigationHelper provided by some templates,
// this event is handled for you.
GetData();
}
This method will bind
public void GetData()
{
listOfSports = new List<Sports>();
for (int i = 1; i < 9; i++)
{
listOfSports.Add(new Sports() { SportsImage = #"ms-appx:///Images/Sports/image" + i.ToString() + ".jpg" });
}
listViewForSports.ItemsSource = listOfSports;
listOfCars = new List<Cars>();
for (int i = 1; i < 14; i++)
{
listOfCars.Add(new Cars() { CarsImage = #"ms-appx:///Images/Cars/image" + i.ToString() + ".jpg" });
}
listViewForCars.ItemsSource = listOfCars;
listOfHomes = new List<Homes>();
for (int i = 1; i < 9; i++)
{
listOfHomes.Add(new Homes() { HomesImage = #"ms-appx:///Images/Homes/image" + i.ToString() + ".jpg" });
}
listViewForHomes.ItemsSource = listOfHomes;
}
public class Cars
{
public string CarsImage { get; set; }
}
public class Sports
{
public string SportsImage { get; set; }
}
public class Homes
{
public string HomesImage { get; set; }
}`
I did with tap event to navigation withing flip view` private void appbarSports_Tapped(object sender, TappedRoutedEventArgs e)
{
// TextBlock a = sender as TextBlock;
// imgLine0.Margin = new Thickness(a.Margin.Left, 55, a.Margin.Right, 1);
flipControl.SelectedIndex = 0;
method(0);
}
private void appbarCars_Tapped(object sender, TappedRoutedEventArgs e)
{
// TextBlock a = sender as TextBlock;
//imgLine0.Margin = new Thickness(a.Margin.Left, 55, a.Margin.Right, 1);
flipControl.SelectedIndex = 2;
method(2);
}
private void appbarHomes_Tapped(object sender, TappedRoutedEventArgs e)
{
// TextBlock a = sender as TextBlock;
// imgLine0.Margin = new Thickness(a.Margin.Left, 55, a.Margin.Right, 1);
flipControl.SelectedIndex = 1;
method(1);
}
I also used for when the user flips so I used FlipView.SelectionChanged event
private void flipControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
FlipView viewControl = sender as FlipView;
int a = viewControl.SelectedIndex;
method(a);
}
This method() is help full for changing imageLine position
public void method(int a)
{
if (imgLine0 != null)
{
switch (a)
{
case 0:
imgLine0.Visibility = Visibility.Visible;
imgLine1.Visibility = Visibility.Collapsed;
imgLine2.Visibility = Visibility.Collapsed;
break;
case 1:
imgLine0.Visibility = Visibility.Collapsed;
imgLine1.Visibility = Visibility.Visible;
imgLine2.Visibility = Visibility.Collapsed;
break;
case 2:
imgLine0.Visibility = Visibility.Collapsed;
imgLine1.Visibility = Visibility.Collapsed;
imgLine2.Visibility = Visibility.Visible;
break;
}
}
}

Error when trying to tap on LongListSelector

I've made a JumpList (by following this tutorial) linked with a LongListSelector, but I can't redirect the user when he taps on an item of the list. I used to do it well with a simple LongListSelector as this one :
<phone:LongListSelector x:Name="lls_Songs" SelectionChanged=lls_Songs_SelectionChanged>
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Margin="5,5,5,5">
<TextBlock Text="{Binding Name}" FontSize="30"/>
<TextBlock Text="{Binding Duration}" FontSize="20" Opacity="0.75"/>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
But now I use this code...
<phone:LongListSelector
x:Name="lls_songs"
Margin="12,35,12,0"
Visibility="Visible"
JumpListStyle="{StaticResource JumpListStyle}"
Background="Transparent"
GroupHeaderTemplate="{StaticResource lls_SongsHeaderTemplate}"
ItemTemplate="{StaticResource lls_SongsTemplate}"
LayoutMode="List"
IsGroupingEnabled="true"
SelectionChanged="lls_songs_SelectionChanged"
HideEmptyGroups ="true"/>
...linked with this code :
<DataTemplate x:Key="lls_SongsTemplate">
<StackPanel VerticalAlignment="Top" Orientation="Horizontal" Margin="5,5,5,5">
<StackPanel Orientation="Vertical">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="détails"/>
<toolkit:MenuItem Header="ajouter à la lecture"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<TextBlock Text="{Binding songName}" FontSize="30" />
<TextBlock Text="{Binding songArtist}" FontSize="20" Opacity="0.75"/>
</StackPanel>
</StackPanel>
</DataTemplate>
here is the lls_Songs_SelectionChanged method :
private void lls_songs_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Song _selectedSong = lls_songs.SelectedItem as Song;
MediaPlayer.Play(_selectedSong);
}
and finaly how I create my songs list :
MediaLibrary _library = new MediaLibrary();
List<MusicInfo> MusicInfoList = new List<MusicInfo>();
int so = _library.Songs.Count;
int _so = 0;
while(_so < so)
{
Song _song = null;
_song = _library.Songs[_so];
MusicInfoList.Add(new MusicInfo(_song.Name, _song.Artist.ToString()));
_so = _so + 1;
}
linked with this class:
public string songName { get; set; }
public string songArtist { get; set; }
public MusicInfo(string _songName, string _songArtist)
{
this.songName = _songName;
this.songArtist = _songArtist;
}
and the jumplist :
private void SortingSongsListsAZ()
{
List<AlphaKeyGroup<MusicInfo>> DataSource = AlphaKeyGroup<MusicInfo>.CreateGroups(MusicInfoList,
System.Threading.Thread.CurrentThread.CurrentUICulture,
(MusicInfo s) => { return s.songName; }, true);
lls_songs.ItemsSource = DataSource;
}
And when I tap on an item of the list, I get this error : "This method does not accept null for this parameter". I don't understand why, anyone would help me ?
Share or check your lls_songs items source binding and code. from your code it appears that
Song _selectedSong = lls_songs.SelectedItem as Song;
_selectedSong is null.
in debug mode see what is the value of SelectedItem. is it Song type or something else?
According to your update, it seems that lls_songs.SelectedItem is of type MusicInfo instead of Song. Fixing your type-casting should remove the error I believe :
MusicInfo _selectedSong = lls_songs.SelectedItem as MusicInfo;
Or better yet this way :
MusicInfo _selectedSong = (MusicInfo)lls_songs.SelectedItem;

Longlist will not update at load

I am having some problems making a long list selector load my data, and i have been unable to find a solution to this problem.
This is my xaml:
<phone:LongListSelector x:Name="animeList"
Margin="0,0,-12,0"
ItemsSource="{Binding Animes}"
Tap="AnimeList_OnTap">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17">
<TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu IsZoomEnabled="false">
<toolkit:MenuItem Header="Add as favorit" Click="AddFavorite" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</TextBlock>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
My view model is simple:
public ObservableCollection<AnimeItemViewModel> _animes { get; set; }
public ObservableCollection<AnimeItemViewModel> Animes
{
get { return _animes; }
set
{
if (value != _animes)
{
_animes = value;
NotifyPropertyChanged("Animes");
}
}
}
And how i load my data:
public MainPage()
{
InitializeComponent();
DataContext = App.ViewModel;
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
ObservableCollection<AnimeItemViewModel> _animes = new ObservableCollection<AnimeItemViewModel>();
foreach (var i in App.AnimeList.List)
_animes.Add(new AnimeItemViewModel() { AId = i.AId, Name = i.Name });
App.ViewModel.Animes = _animes;
}
And lastly just to show that there are data in the list
Update: I also have a search function, and if i enter a search text will the longlist update, but i am for some reason unable to scroll
private void OnKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
ObservableCollection<AnimeItemViewModel> _animes = new ObservableCollection<AnimeItemViewModel>();
foreach (var i in App.AnimeList.List)
if (string.IsNullOrWhiteSpace(SearchTextBox.Text) || i.Name.ToLower().Contains(SearchTextBox.Text.ToLower()))
_animes.Add(new AnimeItemViewModel() { AId = i.AId, Name = i.Name });
App.ViewModel.Animes = _animes;
}
}
Try placing your loading code in OnNavigatedTo. As for the scrolling issue - setting a proper height to the StackPanel. Let me know if it works.

Why there is no PlaceHolder like property in XAML TextBox

Is there any "placeholder type" property availble for textbox in xaml in windows phone 8
There is the PhoneTextBox in the official Windows Phone Toolkit, covered here.
Sample code:
<toolkit:PhoneTextBox Hint="Password"/>
To add toolkit to your project :
Type the following into your package manager console :
PM> Install-Package WPtoolkit
And
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
inside <phone:PhoneApplicationPage tag in the xaml page
Try like this below code:
<TextBox x:Name="InvoiceDate" Text="" Width="300" TextAlignment="Left" Height="30" Grid.Row="0" Grid.Column="3" Grid.ColumnSpan="2" />
<TextBlock IsHitTestVisible="False" Text="Men att läsa" Width="300" TextAlignment="Left" Height="30" Grid.Row="0" Grid.Column="3" Grid.ColumnSpan="2" Padding="5, 5, 5, 5" Foreground="LightGray">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=InvoiceDate}" Value="">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
There is no placeholder property for TextBox. I use the following solution to work around this for a username textbox:
XAML:
<Grid>
<TextBlock Name="UsernamePlaceholder" Text="Username" />
<TextBox Name="UsernameTextBox" Text="" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus"/>
</Grid>
Code:
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
UsernamePlaceholder.Visibility = Visibility.Collapsed;
}
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (sender is TextBox)
{
var textbox = sender as TextBox;
if (string.IsNullOrEmpty(textbox.Text))
{
UsernamePlaceholder.Visibility = Visibility.Visible;
}
}
}
This basically replaces the TextBox with a Grid-element, containing a TextBox and a TextBlock (working as placeholder). Then when the textbox is focused, the textblock is hidden, and when it looses focus the textblock is shown if the textbox is empty.
My solution is based on the answer of PKENO
XAML (UserControl):
<UserControl x:Class="FestivalProject.Controls.TextBoxPH"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<TextBox x:Name="testTextBox" Margin="0" LostFocus="testTextBox_LostFocus" GotFocus="testTextBox_GotFocus"/>
</UserControl>
Code behind UserControl:
public partial class TextBoxPH : UserControl
{
private String _Text;
public String Text
{
get { return _Text; }
set {
_Text = testTextBox.Text = value;
}
}
private String _PlaceHolder;
public String PlaceHolder
{
get { return _PlaceHolder; }
set {
_PlaceHolder =testTextBox.Text = value;
}
}
public TextBoxPH()
{
InitializeComponent();
}
private void testTextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(testTextBox.Text)) testTextBox.Text = PlaceHolder;
}
private void testTextBox_GotFocus(object sender, RoutedEventArgs e)
{
if (testTextBox.Text.Equals(PlaceHolder, StringComparison.OrdinalIgnoreCase)) testTextBox.Text = string.Empty;
}
}
XAML (in Window):
<txtPH:TextBoxPH Margin="5" Grid.ColumnSpan="2" PlaceHolder="PlaceholderText"/>
Probably not the most efficient way, but it works.