I'm using a LongListSelector for a WP8 app. I searched on several websites but did not found if there was a way to know the index of the item the user taped in the List.
If anyone has an idea, it would be nice.
Thanks
`
<phone:LongListSelector x:Name="ListeNotes" Height="535" Width="426" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="36" Margin="54,0,0,0">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Titre}"/>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
`
I'd create in code-beind or ViewModel (depending on what are you using), public variable
Public Int32 itemSelectedIndex {get;set;} //This is a public variable, therefore add it inside your class
and bind it to SelectedIndex as following:
<phone:LongListSelector x:Name="ListeNotes" Height="535" Width="426" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="36" Margin="54,0,0,0" SelectedIndex ="{Binding itemSelectedIndex, UpdateSourceTrigger = PropertyChanged}">
don't forget to add datacontext reference in code behind
Public void MainWindow()
{
InitializeComponents();
this.DataContext = this;//this makes sure that you can bind public varibles to XAML
}
Afterwards you simply reference itemSelectedIndex anywhere in your code and it will return selected value (e.g. System.Windows.MessageBox.Show(itemSelectedIndex.ToString());
In the handler:
SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles ListeNotes.SelectionChanged`
The "sender" is the ListBox. So all you have to do is cast "sender" to ListBox, and use its SelectedIndex property.
Dim listBox As ListBox = CType(sender, ListBox)
Dim tappedIndex = listBox.SelectedIndex
you can get it via
Dim num As Integer = (sender as LonglistSelector).Datasource.IndexOf((sender as LonglistSelector).SelectedItem)
The solution was not found...
In fact I just said the user can't have twice the same Note object, and I use the IndexOf method in my List(Of Note) to get the index of the SelectedItem in the LongListSelector.
Related
I have a custom user control like this
<Grid>
<ListView x:Name="LView" SelectedIndex="{Binding SelectedIndex}" ItemsSource="{x:Bind
ItemsSource, Mode=OneWay}" Width="{x:Bind Width}" Height="{x:Bind Height}" VerticalAlignment="Stretch" SelectionMode="Multiple" />
</Grid>
Now in Codebehind, I am trying to get its SelectedIndex using a dependency property
public int SelectedIndex
{
get { return (int)GetValue(SelectedIndexProperty); }
set { SetValue(SelectedIndexProperty, value); }
}
public static readonly DependencyProperty SelectedIndexProperty =
DependencyProperty.Register("SelectedIndex", typeof(int), typeof(CustomControl), new PropertyMetadata(0));
And In my main page, I am accessing that dependency property like this
<local:CustomControl Grid.Column="0" Grid.Row="0" Width="400" Loaded="EditTextControl_Loaded"
x:Name="MultiCombo" ></local:CustomControl>
Codebehind
var selIndex = MultiCombo.SelectedIndex;
but neither an event is getting fired on the selectedIndexChange (in the main page) nor I am getting any value on my main page. How can I make this happen?
Note: I have uploaded complete code here
In your CustomControl page, the mode you bind the SelectedIndex property of ListView with SelectedIndex dependency property is OneWay, when you select other items in ListView, the SelectedIndex dependency property won't change, so the value of MultiCombo.SelectedIndex in main page won't change. In this case, you need to set the mode as TwoWay.
CustomControl.xaml:
<ListView x:Name="LView" SelectedIndex="{x:Bind SelectedIndex,Mode=TwoWay}" ItemsSource="{x:Bind ItemsSource, Mode=OneWay}" Width="{x:Bind Width}" Height="{x:Bind Height}" VerticalAlignment="Stretch" SelectionMode="Multiple" />
In your main page, you subscribe the DataContextChanged event to get the SelectedIndex dependency property, but this event only occurs when the DataContext of current page changes. If you want to trigger method in your main page when the selected index of ListView changes, you can define a dependency property in your main page to bind with the SelectedIndex dependency property of CustomControl and add a static callback method that is automatically invoked whenever a property value change is detected. For example:
MainPage.cs:
public int MPSelectedIndex
{
get { return (int)GetValue(MPSelectedIndexProperty); }
set { SetValue(MPSelectedIndexProperty, value); }
}
public static readonly DependencyProperty MPSelectedIndexProperty =
DependencyProperty.Register("MPSelectedIndex", typeof(int), typeof(MainPage), new PropertyMetadata(0, new PropertyChangedCallback(OnDataChanged)));
private static void OnDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MainPage currentPage = d as MainPage;
int count = currentPage.MultiCombo.SelectedIndex;
}
MainPage.xaml:
<local:CustomControl Grid.Column="0" Grid.Row="0" Width="400" Loaded="EditTextControl_Loaded" x:Name="MultiCombo" SelectedIndex="{x:Bind MPSelectedIndex,Mode=TwoWay}" >
</local:CustomControl>
Note:
Since you set the SelectionMode of ListView is Multiple, when you select the first item, the SelectedIndex is 0 and then you also select the second item, the SelectedIndex is still 0. Only when you unselect the first item, the SelectedIndex will change and the method will be triggered.
I think the issue is that you are not binding the SelectedIndex properly.
Instead of binding to self/ ListView's SelectedIndex, you need to bind it to the CustomControl's SelectedIndex DependencyProperty.
<ListView ... SelectedIndex="{Binding
Path=SelectedIndex,
Mode=TwoWay,
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type UserControl}}}" .../>
You might need to change the type to your CustomControl's type as necessary (if it is not UserControl).
I've got this function that receives a digital output pin address uscita as Integer and status high as boolean, and updates the pin-out and fills color red in a LED-like Ellipse on the UI.
Private Function comandaUscita(ByVal uscita As Integer, ByVal high As Boolean) As Boolean
If high Then
Select Case uscita
Case 1
If gpin1 IsNot Nothing Then gpin1.Write(GpioPinValue.High)
LED1.Fill = redBrush
Case 2
If gpin1 IsNot Nothing Then gpin2.Write(GpioPinValue.High)
LED2.Fill = redBrush
...
End Select
Return True
End If
End Function
The function is called every 500ms via a timer.
Debugging shows that the function is working only once.
From the second time and for all other times, the function throws an exception
The application called an interface that was marshalled for a
different thread. (Exception from HRESULT: 0x8001010E
(RPC_E_WRONG_THREAD))
How can I prevent that without using the f... dispatchers and similar cumbersome stuff.
Additionally, how to refresh the UIelements, given that no .Refresh method exists, again without using the f... dispatchers?
The old winforms didn't have these issues... ah, the old times.
My UI XAML looks something like this:
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Height="60"
Margin="10,10,10,569"
Width="340">
<TextBlock x:Name="DelayText1"
Text="Uscita digitale 1"
Margin="10"
TextAlignment="Center"
FontSize="26.667"
HorizontalAlignment="Right" />
<Ellipse x:Name="LED1"
Fill="LightGray"
Stroke="White"
Width="25"
Height="25"
Margin="10,-40,10,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
RenderTransformOrigin="3.524,-1.209"/>
</StackPanel>
Data Binding!
Create an LED ViewModel object, bind one to each LED UI element. Give the LED ViewModel a "Fill" property of the appropriate type. Then, every 500 ms when your timer ticks, update the property and fire off the PropertyChanged event. When the UI element sees the PropertyChanged event, it will refresh "Fill"
It's a bit of an architecture change, but you won't need to worry about using the dispatcher.
This website http://blogs.msdn.com/b/jerrynixon/archive/2012/10/12/xaml-binding-basics-101.aspx has an OK example of binding a string to a button's text. See "Binding a property" - you're going to need to do something similar, but you'll be binding to "Fill"
This question: How can I bind a background color in WPF/XAML? is also doing something pretty similar to what you're trying to do.
Followup to address questions in comments
In your viewmodel, you would need to create a property of type "Brush" and then in the XAML, bind it to the Fill property of the ellipse like:
//The viewmodel:
public sealed class LedViewModel: INotifyPropertyChanged {
// Update this property and fire the PropertyChanged
// event to propagate the change to the UI.
public Brush LedFill { get; set; }
. . .
//In the XAML:
<Ellipse x:Name="LED Whatever"
Fill="{Binding Path=LedFill}"
. . .
Sorry - I just realized that my example is c# and you're doing VB - the XAML part will be the same - The syntax for your ViewModel will be a little different from mine.
Ok, so what I did:
Public NotInheritable Class LedViewModel
Implements INotifyPropertyChanged
Private _LEDFill As Brush
Public Property LEDfill As Brush
Get
Return _LEDFill
End Get
Set(value As Brush)
_LEDFill = value
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler
Implements INotifyPropertyChanged.PropertyChanged
End Class
in the XAML
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Height="60" Margin="10,10,10,569" Width="340">
<TextBlock x:Name="DelayText1" Text="Uscita digitale 1" Margin="10" TextAlignment="Center" FontSize="26.667" HorizontalAlignment="Right" />
<Ellipse x:Name="LED1" Fill="{Binding Path=LEDfill}" Stroke="White" Width="25" Height="25" Margin="10,-40,10,0" HorizontalAlignment="Left" VerticalAlignment="Top" RenderTransformOrigin="3.524,-1.209"/>
</StackPanel>
And in the code? LED1.fill = whatever?
I work an a Windows 8 application which shows a GridView on one page. When ever the user selects an item of this grid and clicks on a button, the next page is loaded with detail information of the selected item.
I am using MVVM for this and have a DelegateCommand from Prims:
public DelegateCommand<Route> ShowRouteDetailsCommand { get; private set; }
This command is initialized inside the constructor:
this.ShowRouteDetailsCommand = new DelegateCommand<Route>(this.ShowRouteDetails);
The navigation is done by Prisms navigation service:
private void ShowRouteDetails(Route route)
{
this.NavigationService.Navigate(PageNames.RouteDetails, route.Id);
}
The routes are shown inside a GridView:
<GridView x:Name="RouteGrid"
ItemsSource="{Binding Routes}"
SelectionMode="Single">
<GridView.ItemTemplate>
<DataTemplate> ...
The command is currently added inside the app bar (just for testing):
<AppBarButton Command="{Binding ShowRouteDetailsCommand}"
CommandParameter="{Binding SelectedValue,
ElementName=RouteGrid, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Icon="Forward" />
My problem is, that the parameter of ShowRouteDetails is allways empty. It doesn't even matter if I try GridViews SelectedValue or SelectedItem property.
I know that I could easily add a SelectedRoute property, bind the SelectedItem to it and use it in ShowRouteDetails but this seems dirty to me.
Why don't you just create a var in your viewModel and bind it to the SelectedItem of the gridView? In this way, when you run the command, you have only to read the value of that var.
<GridView x:Name="RouteGrid" ItemsSource="{Binding Routes}"
SelectionMode="Single" SelectedItem="{Binding myVar}">
<GridView.ItemTemplate>
<DataTemplate>
I'm a fairly novice programmer, and making a Windows Store App. I have an object that contains an ObservableCollection(Of T) that I want to group for display in a ListView. Using LINQ to return a set of grouped items seems like it would be the best and easiest choice. Every piece of documentation I could find says that Group By returns IEnumerable(Of IGrouping(Of TKey, TItem)) and you set CollectionViewSource.IsSourceGrouped to True, bind to the CVS and it should all work perfectly. Right?
Not so much.
I have a class that contains
Public Property Items As ObservableCollection(Of Item)
Public ReadOnly Property GroupedItems As IEnumerable
Get
' Return grouped items
End Get
End Property
And in the XAML for the page, where GroupedItems is set as the Page's DataContext in code-behind:
<Page.Resources>
<CollectionViewSource x:Name="GroupedItems" Source="{Binding}" IsSourceGrouped="True" />
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<ListView ItemsSource="{Binding Source={StaticResource GroupedItems}}">
<ListView.GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<!-- Template -->
</DataTemplate>
</GroupStyle.HeaderTemplate>
</ListView.GroupStyle>
<ListView.ItemTemplate>
<DataTemplate>
<!-- Template -->
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
Now, if I bind the ListView to the ObservableCollection(Of Item) directly, the ListView renders all the items as expected, following the ItemTemplate. But when it is bound to the supposedly-grouped CollectionViewSource, the ListView renders the groups according to the HeaderTemplate, but it doesn't render any of the items within the group.
I've inspected the results of the LINQ logic:
Dim x = From i As Item In Items
Group i By Key = i.SubItem Into Group
And x has a Key property and a Group property, though it is some kind of IEnumerable(Of anonymous) type rather than an IEnumerable(Of IGrouping(Of TKey, TItem)).
So what am I doing wrong here? Is there another caveat to the VB.NET implementation of LINQ that I'm missing? Is there a property I'm forgetting to set? What is the right way to do this?
I found a solution, though I don't know that it is the ideal solution. Because the result of the LINQ query places the items in the Group property of its anonymous type, CollectionViewSource needs to know that. So by adding ItemsPath="Group" to the XAML defining the CollectionViewSource, it now displays both the group headers and the containing items.
Sorry for the basic questions, but I've been searching the web for a number of days and can't find the answer to these questions.
I've created a Custom Control, and I will be placing a large number of instances of that Custom Control on my xaml page. In working with that Custom Control in the VB Code Behind, how do I do the following?
How do I reference the name of the Custom Control (in my VB code) which was clicked with the MouseLeftButtonDown event? For example, if I have 10 instances of my Custom Control in xaml, each with a different x:name (say 1-10), when a particular instance is clicked, how can I see which one was clicked? I've tried a number of things including e.OriginalSource.Name (which returns the component within the control which was clicked and not the name of the instance of the control).
My Custom Control consists of numerous parts and pieces (Rectangles, Lines, Text, etc). Each of these items is a part of my layer. In VB code, once I can reference a particular Control, how can I hide or change certain parts of that control (such as hiding a Line, and changing the text). Also, I need to modify more than just the control which was clicked, so I need to be able to access properties of all of the controls, not just what was clicked. For example, if I click Control instance Test1, I also need to modify Test2, Test3, and Test5 in some way.
Here is some test code I through together as part of a Silverlight project using MS Blend 2. My control is much larger, and I need 200 - 250 instances/copies of that custom control, so I really need to know which control instance/copy was clicked.
My UserControl:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="MyControl1"
x:Name="UserControl"
d:DesignWidth="60" d:DesignHeight="59">
<Grid x:Name="LayoutRoot" MouseLeftButtonDown="OnMouseClick">
<Rectangle x:Name="Rectangle1" Fill="#FFFFFFFF" Stroke="#FF000000"/>
<TextBox Background="{x:Null}" x:Name="TextBox1" Text="Test" TextWrapping="Wrap"/>
<Ellipse x:Name="Circle1" Fill="{x:Null}" Stroke="#FF000000"/>
<Path Margin="1,29,0,29" x:Name="Line1" Fill="{x:Null}" Stretch="Fill" Stroke="#FF000000" Data="M74,80 L132,80"/>
<Path Margin="0,0,1,14" x:Name="Line2" VerticalAlignment="Bottom" Height="1" Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF000000" Data="M73,95 L131,95"/>
<Path Margin="0,0,0,4" x:Name="Line3" VerticalAlignment="Bottom" Height="1" Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF000000" Data="M73,105 L132,105"/>
</Grid>
</UserControl>
My xaml App using the Custom Control:
<Grid x:Name="LayoutRoot">
<Tester:MyControl1 HorizontalAlignment="Left" Margin="56,54,0,0" VerticalAlignment="Top" Width="60" Height="60" x:Name="Test1"/>
<Tester:MyControl1 HorizontalAlignment="Left" Margin="116,54,0,0" VerticalAlignment="Top" Width="60" Height="60" x:Name="Test2"/>
<Tester:MyControl1 HorizontalAlignment="Left" Margin="176,54,0,0" VerticalAlignment="Top" Width="60" Height="60" x:Name="Test3"/>
<Tester:MyControl1 HorizontalAlignment="Left" Margin="236,54,0,0" VerticalAlignment="Top" Width="60" Height="60" x:Name="Test4"/>
<Tester:MyControl1 HorizontalAlignment="Left" Margin="296,54,0,0" VerticalAlignment="Top" Width="60" Height="60" x:Name="Test5"/>
</Grid>
My Custom Control VB Code:
Partial Public Class MyControl1
Public Sub New()
MyBase.New()
Me.InitializeComponent()
' Insert code required on object creation below this point.
End Sub
Private Sub OnMouseClick(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs)
Dim int_Temp As Integer
Dim str_InstanceName As String
str_InstanceName = "1.What code here tells me the name of the instance which was checked? Test1, Test2, etc. for example."
int_Temp = MessageBox.Show(str_InstanceName, "Testing", MessageBoxButton.OK)
'2.What code here lets me manipulate parts of my control instances (and not just the instance which was clicked)?
'I want to hide Test1.Line1 and Test2.Line3 and Test3.Circle1 and change the background of Test5.Rectangle1 for example.
End Sub
End Class
Thanks in advance, and sorry to all the C# experts that I need this in VB.
It looks like you're talking about a User Control, not a Custom Control. There is a little bit of a difference when working with the two. You can read more about those differences here:
Custom Controls Vs. User Controls
In this case, you want to be looking at the 'sender' object in your event handler. You want to cast the sender as your User Control (this will be safe since you're only using that event handler on controls of your type).
Private Sub OnMouseClick(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs)
Dim senderAsControl As MyControl1 = sender As MyControl1
' Get the instance name from the sender
Dim instanceName As String = senderAsControl.Name
' You can also access your children from the sender once cast
senderAsControl.Rectangel1.IsVisible = False ' Hide the rectangle
End Sub
I can't compile the code to double check myself at the moment...but it should give you the idea.