Tap and hold Listbox Windows Phone - c#

Does anybody know how can I add event whenever I press my listbox it will directly run my code. I need it to change my listbox selected item. This is my xaml:
<ListBox x:Name="ListNabi" SelectionChanged="ListNabi_SelectionChanged" ItemsSource="{Binding}" Tap="ListNabi_Tap" Hold="ListNabi_Hold">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="5,0,5,0">
<!--<Image Source="{Binding ImageSource}" Stretch="None"/>-->
<Grid Width="480" Background="White">
<Image x:Name="listDaun" Source="/Images/Button/Button List.png"
Margin="0,5,5,5" Width="38" HorizontalAlignment="Left"></Image>
<TextBlock x:Name="namaNabi" TextWrapping="NoWrap"
Text="{Binding Name}" FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="36" Foreground="#00ADCE" Margin="40,5,0,5"></TextBlock>
<Rectangle Margin="0,50,0,0" Height="2" Fill="#00ADCE" Width="480"/>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And in CS I did like this:
private void ListNabi_Hold(object sender, System.Windows.Input.GestureEventArgs e)
{
changeColor("#00ADCE", "#FFFFFF", "#FFFFFF", "/Images/Button/Button List1.png");
}
private void ListNabi_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
if (ListNabi.SelectedIndex != -1)
{
id = ListNabi.SelectedIndex;
}
MessageBox.Show("tes");
changeColor("#00ADCE", "#FFFFFF", "#FFFFFF", "/Images/Button/Button List1.png");
}
private void ListNabi_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ListNabi.SelectedIndex != -1)
{
id = ListNabi.SelectedIndex;
changeColor("#00ADCE", "#FFFFFF", "#FFFFFF", "/Images/Button/Button List1.png");
NavigationService.Navigate(new Uri("/Pages/25_Nabi/DetailPage.xaml?id="
+ ListNabi.SelectedIndex, UriKind.Relative));
ListNabi.SelectedIndex = -1;
}
}
But it will only run my code (in this context changeColor()) whenever I hold my listbox after some time or after I release my finger. Is there any event I can use to start run my code whenever my finger start touch?

For that use the following events: ManipulationStarted, ManipulationDelta and ManipulationCompleted. You will get everything you need from positions to the number of different touch points.
You can do sophisticated things with it like dragging and pinching.

Related

Get the parent ObservableCollection which Item selected - WP8

I'm writing an app to play streaming music, In app I have many list (Ranking list, Search Result List, Highlight song list .....), Each list have a same datatemplate which I bind to a LongListSelector for each Page. So I use this datatemplate as resources and put it in app.xaml
<DataTemplate x:Key="BasicVideoTemplate">
<Grid Tap="ChangeSong_Tap" RowsAuto="50,50" ColumnsAuto="150,*" Background="White" Margin="5,0,5,10">
<Grid.ColumnDefinition>
<ColumnDefinition Width = "150"/>
<ColumnDefinition Width = "*"/>
</Grid.ColumnDefinition>
<Grid.RowDefinition>
<RowDefinition Height = "50"/>
<RowDefinition Height = "50"/>
</Grid.RowDefinition>
<Border BorderThickness="1" BorderBrush="Black" Grid.RowSpan="2" Grid.Column="0" VerticalAlignment="Center" Margin="5,0,5,0">
<Image Source="{Binding Cover}"/>
</Border>
<TextBlock Text="{Binding Name}" Grid.Row="0" Grid.Column="1" Style="{StaticResource BlackTextBlock}" Margin="5,0,0,0"/>
<TextBlock Text="{Binding Artist}" Grid.Row="1" Grid.Column="1" Foreground="Black" Margin="5,0,0,0"/>
<!-- .............. -->
</Grid>
</DataTemplate>
And this code (which i put in app.xaml.cs) to select a song from list, create a AudioTrack from this item and navigate to playSongPage:
private void ChangeSong_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
var item = (SongItemModel)(sender as FrameworkElement).DataContext;
App.Model.ChangeSong(item.Id); /// this code will create a audio track for this item
(Application.Current.RootVisual as PhoneApplicationFrame).Navigate(new Uri("/Pages/DetailSongPage.xaml", UriKind.Relative));
}
Problem here is, I have to create a List< AudioTrack> for my playlist , So how can I get the parent list of clicked item and add it to the List< AudioTrack> , while all this code was put in app.xaml.cs ???
I would handle it in the SelectionChanged event of each longlistselector instead. The whole Tap thing on the grid doesn't sit well with me.
<phone:LongListSelector x:Name="myLSS" SelectionChanged="myLSS_SelectionChanged"/>
// event handler changes to
private void myLSS_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
LongListSelector lls = sender as LongListSelector; // get lls
var item = (SongItemModel) lls.SelectedItem;
App.Model.ChangeSong(item.Id); /// this code will create a audio track for this item
// now your ObservableCollection is just the ItemsSource, save a reference to it
// in the State manager so you can reference it on another page if you wish
ObservableCollection<SongItemModel> obs = (ObservableCollection<SongItemModel>) lls.ItemsSource;
PhoneApplicationService.Current.State["current_obs"] = obs;
// navigate..............
(Application.Current.RootVisual as PhoneApplicationFrame).Navigate(new Uri("/Pages/DetailSongPage.xaml", UriKind.Relative));
}

How to use (if possible) same source a tap event uses in a ContextMenu button click?

Im tweaking a Sound Player app to try and include a Save as Ringtone function. App uses Tiles and a Viewmodel. Tapping each tile plays a sound. I added a Context Menu to the Data Template to give the option on a Tap and Hold event to save that sound as a Ringtone. I am having some issues figuring out just how to use the same source as the Tiles use to play the sound. Below, first code is portion of the Mainpage.xaml. Then the c# code. What I have set at the bottom of the MainPage.cs for the _customRingtone Source is wrong. The emulator stops at "SoundData data = selector.SelectedItem as SoundData;" I cant figure out how to do the source in a similar way the Tile taps get the audio for playing it. I didnt post the ViewModel but can if you want me to. That is where the Tile Groups and sounds are loaded.
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="SoundTileDataTemplate">
<StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Click="Save_Click" Header="Save as Ringtone" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<Grid Background="{StaticResource PhoneAccentBrush}"
Margin="0, 0, 12, 12">
<Grid VerticalAlignment="Top"
HorizontalAlignment="Right"
Width="40"
Height="40"
Margin="0, 6, 6, 0">
<Ellipse Stroke="{StaticResource PhoneForegroundBrush}"
StrokeThickness="3" />
<Image Source="/Assets/AppBar/Play.png" />
</Grid>
<StackPanel VerticalAlignment="Bottom">
<TextBlock Text="{Binding Title}" Margin="6, 0, 0, 6" />
</StackPanel>
</Grid>
</StackPanel>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<MediaElement
Name="AudioPlayer"
Volume="1" />
<!--Pivot Control-->
<phone:Pivot Title="{Binding Path=LocalizedResources.ApplicationTitle,
Source={StaticResource LocalizedStrings}}">
<phone:PivotItem Header="{Binding Animals.Title}">
<phone:LongListSelector x:Name="Animal"
SelectionChanged="LongListSelector_SelectionChanged"
Margin="0,0,-12,0"
ItemsSource="{Binding Animals.Items}"
LayoutMode="Grid"
GridCellSize="150,150"
ItemTemplate="{StaticResource SoundTileDataTemplate}"
/>
</phone:PivotItem>
public partial class MainPage : PhoneApplicationPage
{
private readonly SaveRingtoneTask
_CustomRingtone;
// Constructor
public MainPage()
{
InitializeComponent();
// Set the data context of the listbox control to the sample data
DataContext = App.ViewModel;
_CustomRingtone = new SaveRingtoneTask();
_CustomRingtone.Completed +=
customeRingtone_Completed;
BuildLocalizedApplicationBar();
}
// Load data for the ViewModel Items
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
}
}
private void LongListSelector_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
LongListSelector selector = sender as LongListSelector;
// verifying our sender is actually a LongListSelector
if (selector == null)
return;
SoundData data = selector.SelectedItem as SoundData;
// verifying our sender is actually SoundData
if (data == null)
return;
private void customeRingtone_Completed(object sender, TaskEventArgs e)
{
if (e.TaskResult == TaskResult.OK)
{
MessageBox.Show(#"Saved");
}
else if (e.TaskResult == TaskResult.Cancel)
{
MessageBox.Show(#"Canceled");
}
else
{
MessageBox.Show(#"Not Saved");
}
}
private void Save_Click(object sender, System.Windows.RoutedEventArgs e)
{
LongListSelector selector = sender as LongListSelector;
SoundData data = selector.SelectedItem as SoundData;
**_CustomRingtone.Source = new Uri(data.FilePath, UriKind.RelativeOrAbsolute**);
_CustomRingtone.DisplayName = "Ring";
_CustomRingtone.Show();
}
You Save_Click event handler is not passed a LLS, but a context MenuItem. The DataContext of the MenuItem is the object you are after.
private void Save_Click(object sender, System.Windows.RoutedEventArgs e)
{
var element = (FrameworkElement)sender;
SoundData data = element.DataContext as SoundData;
_CustomRingtone.Source = new Uri(data.FilePath, UriKind.RelativeOrAbsolute**);
_CustomRingtone.DisplayName = "Ring";
_CustomRingtone.Show();
}

how to change MediaElement source when ListPicker_SelectionChanged?

I'm trying to bind item from list picker to MediaElement Source when user I have the uri store in ListPickerItem Tag my problem I want to change the bleep.Source when ListPicker_SelectionChanged but my problem how to selected and cast it ?
private void ListPicker_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
// TODO: Add event handler implementation here.
bleep.Source = lp_sound.SelectedItem.ToString();
}
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<MediaElement x:Name="bleep" Source="soundFiles\ROAR.wav" AutoPlay="False" Visibility="Collapsed"/>
<Button x:Name="ButtonPlay" Content="play" HorizontalAlignment="Left" Margin="170,404,0,0" VerticalAlignment="Top" Click="ButtonPlay_Click"/>
<toolkit:ListPicker x:Name="lp_sound" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="408" SelectionChanged="ListPicker_SelectionChanged">
<toolkit:ListPickerItem x:Name="BestRoar" Content="Sound1" Tag="soundFiles\ROAR.wav" ></toolkit:ListPickerItem>
</toolkit:ListPicker>
</Grid>
You can do this to get results. I assumed that you have used local media file in your listpicker.
private void ListPicker_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e){
ListPickerItem item = lp_sound.SelectedItem as ListPickerItem;
if(item!=null)
bleep.Source = new Uri(Convert.ToString(item.Tag), UriKind.Relative);
}
Hope this will help.

How to make the canvas detect touch input properly in C#?

Basically, I'm trying to make the canvas listen for a touch input (tap) and will increment the number of taps on screen. It isn't working when I touch the screen on my device. I debugged my code and nothing seems out of the ordinary except that the touch is not detected. I checked ZIndex and the canvas is in front of the screen to be touchable. How do I make it work?
XAML:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBlock Name="counter" FontSize="150" HorizontalAlignment="Center" TextWrapping="Wrap" Text="0" VerticalAlignment="Center" Margin="188,10,187,397"/>
<Button Content="Reset" HorizontalAlignment="Stretch" Margin="-18,535,-18,0" VerticalAlignment="Top" Click="Button_Click"/>
<Canvas ZIndex="0" Name="Canvas" HorizontalAlignment="Center" Height="535" VerticalAlignment="Top" Width="446" MouseLeftButtonDown="Canvas_MouseLeftButtonDown" MouseLeftButtonUp="Canvas_MouseLeftButtonUp" MouseLeave="Canvas_MouseLeave"/>
</Grid>
C#:
int taps = 0; // create var to detect number of times, user touches the screen
// Constructor
public MainPage()
{
InitializeComponent();
}
// method to register the touch as the finger is placed on the screen
private void Canvas_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//Canvas c = sender as Canvas;
counter.Text = "TOUCHED!";
}
//method register the touch as the finger is lifting up from the screen
private void Canvas_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//Canvas c = sender as Canvas;
taps++;
counter.Text = taps.ToString(); //convert var from int to string
}
//method register the touch as the finger leaves the area of the screen
private void Canvas_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
//Canvas c = sender as Canvas;
MessageBox.Show("You left the screen without lifting your finger. That does not count as a tap!", "Caution!", MessageBoxButton.OK);
}
// method to reset the counter to zero when button is pressed and released
private void Button_Click(object sender, RoutedEventArgs e)
{
taps = 0; // reset the count
counter.Text = taps.ToString(); // convert var from int to string
}
I don't know why you want to do it with Canvas - it won't work as you have nothing in this Canvas, so it can't register your click/tap, Canvas is also hard to adjust to screen. I think it can be done simpler way if you want to do it with MouseUp/Down - subscribe directly to Grid containing your elements instead of filling this Grid with additional Canvas:
In XAML:
<Grid x:Name="ContentPanel" Margin="12,0,12,0" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="7*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<TextBlock Name="counter" FontSize="150" HorizontalAlignment="Center" TextWrapping="Wrap" Text="0" VerticalAlignment="Center" Grid.Row="0"/>
<Button Content="Reset" HorizontalAlignment="Stretch" VerticalAlignment="Center" Click="Button_Click" Grid.Row="1"/>
<TextBlock Name="Touched" FontSize="50" HorizontalAlignment="Center" TextWrapping="Wrap" Text="Touched" VerticalAlignment="Center" Visibility="Collapsed" Grid.Row="2"/>
</Grid>
In code behind:
private int taps = 0;
public MainPage()
{
InitializeComponent();
ContentPanel.MouseLeftButtonDown += ContentPanel_MouseLeftButtonDown;
ContentPanel.MouseLeftButtonUp += ContentPanel_MouseLeftButtonUp;
}
private void ContentPanel_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
taps++;
counter.Text = taps.ToString(); //convert var from int to string
Touched.Visibility = Visibility.Collapsed;
}
private void ContentPanel_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
Touched.Visibility = Visibility.Visible;
}
// method to reset the counter to zero when button is pressed and released
private void Button_Click(object sender, RoutedEventArgs e)
{
taps = 0; // reset the count
counter.Text = taps.ToString(); // convert var from int to string
}
As you can see I've subscribed to Grid events (which covers whole screen) - but to make it work I had to set its Background Brush to Transparent, otherwise it will work only if you touch text.
There are many other ways to make your App work, but I hope this will help.
Is there a reason why you don't use the touch-events?
Instead of using MouseLeftButtonDown and MouseLeftButtonUp you should use TouchDown and TouchUp.
Only when you don't handle the touch events or the manipulation events they will be mapped to mouse events. In my experience with touch a single tap also not always gets mapped to MouseLeftButtonDown. As far as I know you could also with mouse events only recoginse one finger. When you want to count more fingers it's necessary to use the TouchDown/TouchUp events.
The problem lies in the overlapping style of the grid
so either make grid rows or define a stackpanel inside the grid, something like this.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<stackpanel>
<TextBlock Name="counter" FontSize="150" HorizontalAlignment="Center" TextWrapping="Wrap" Text="0" Margin="0,0,0,0"/>
<Canvas ZIndex="0" Name="Canvas" HorizontalAlignment="Center" Height="535" VerticalAlignment="Top" Width="446" MouseLeftButtonDown="Canvas_MouseLeftButtonDown" MouseLeftButtonUp="Canvas_MouseLeftButtonUp" MouseLeave="Canvas_MouseLeave"/>
<Button Content="Reset" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Top" Click="Button_Click"/>
</stackpanel>
</Grid>
Try and check now.
You should set your Background property. If you don't want any background set it to Transparent:
<Canvas ZIndex="99" Background="Transparent" Name="Canvas" HorizontalAlignment="Center" Height="535" VerticalAlignment="Top" Width="446" Tapped="Canvas_CountMyTaps"/>
(If you want the canvas to be on Top be sure to make it have a greater ZIndex than the other elements that it overlaps)
If not set (the default value is null) the element won't capture any taps/click etc, it will be as if they "fall through".
Also, consider using the Tapped event which is a "higher level" event that will respond to clicks, taps with the finger, stylus, etc.

Unable to handle MouseDown event from ListView Item (Label)

I have a List View which I am populating with Labels via code. When the user clicks the label I want to handle the MouseDown event, but it doesn't fire. The preview mouse down does fire.
I understand there is something here about routing / bubbling events which I guess is going to the issue I'm hitting, this is a concept I'm yet to grasp.
I cannot use the preview event as this does not contain the object I need (the label information does not get assigned until the second click of the label, so I assume I need the MouseDown and not the preview)
Appreciate your time.
XAML
<telerik:RadTabItem x:Name="Media" Header="Media" Height="22" Width="100">
<Grid x:Name="ListboxMedia">
<ListView x:Name="ListViewImages" HorizontalAlignment="Left" Height="303" Margin="697,10,0,0" VerticalAlignment="Top" Width="178" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" IsTabStop="True" TabIndex="3" MouseDown="ListViewImages_MouseDown" PreviewMouseDown="ListViewImages_PreviewMouseDown">
<ListView.View>
<GridView>
<GridViewColumn x:Name="ListViewImageColumn" Header="Images" Width="178" />
</GridView>
</ListView.View>
</ListView>
<Button x:Name="BtnUpload" Content="Upload" Height="24" Margin="809,318,38,0" VerticalAlignment="Top" Click="BtnUpload_Click"/>
<Button x:Name="BtnDownload" Content="Download" Height="24" Margin="728,318,109,0" VerticalAlignment="Top"/>
<Image x:Name="ImageViewPort" HorizontalAlignment="Left" Height="293" Margin="21,20,0,0" VerticalAlignment="Top" Width="581"/>
</Grid>
</telerik:RadTabItem>
Method which populates Labels into ListViewImages
void PopulateMedia()
{
var collectImages = new Media().CollectMediaForAsset(_assetId);
int i = 1;
foreach (var collectImage in collectImages)
{
var label = new Label();
label.Tag = collectImage.FileName;
label.Content = "Image" + i.ToString();
ListViewImages.Items.Add(label);
i++;
}
}
Handlers
private void ListViewImages_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
Debug.WriteLine("Clicked Down"); //does not work
}
private void ListViewImages_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
Debug.WriteLine("Clicked Preview"); //works
}
Used selection changed event instead

Categories

Resources