I would like to simply show a border around the currently selected item in my LongListSelector. I have set an ItemTemplate for my LongListSelector, but I am unsure of how to modify the Border so that only the currently selected item contains a border.
MainPage.xaml
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="ItemTemplate">
<!-- BorderBrush of all items are currently set to PhoneAccentBrush, need only currently selected item! -->
<Border x:Name="brd" CornerRadius="10" BorderBrush="{StaticResource PhoneAccentBrush}" Width="Auto" BorderThickness="3">
<Viewbox Width="108" Height="108">
<Image x:Name="recentImage" Source="{Binding Source}" Margin="6,6" Width="108"/>
</Viewbox>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu x:Name="imgListContextMenu" Background="{StaticResource PhoneChromeBrush}">
<toolkit:MenuItem Foreground="{StaticResource PhoneForegroundBrush}" Header="delete" Click="deleteContextMenuItem_Click"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</Border>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
...
<phone:LongListSelector x:Name="Recent" Margin="0"
SelectionChanged="recent_SelectionChanged"
toolkit:TiltEffect.IsTiltEnabled="True"
LayoutMode="Grid" GridCellSize="108,108"
ItemTemplate="{StaticResource ItemTemplate}"
/>
Currently all of the items within the LongListSelector show the border. I would prefer to modify this in the code behind, but what I have thus far does not work
MainPage.xaml.cs
private void recent_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var item = sender as LongListSelector
item.BorderBrush = App.Current.Resources["PhoneAccentBrush"] as SolidColorBrush;
}
Any ideas?
When you access the selected item, you should access it as a border and not as a LongListSelector because that's how you show each item, while the LongListSelector is the container. You also forgot a semi-colon on the 3rd row, I've added it for you.
Your new code would be:
private void recent_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var item = sender as Border;
item.BorderBrush = App.Current
.Resources["PhoneAccentBrush"] as SolidColorBrush;
}
Related
In Windows Universal app, I have a pivot table which every tab content have gridview, gridview items are multi select mode,
What I want that if any one item once checked (selected), then it unable to unselect(uncheck)
<Grid DataContext="{Binding Path=Value}">
<GridView x:Name="categoryItemsGV"
Margin="5,5,0,0"
SizeChanged="categoryItemsGV_SizeChanged"
IsItemClickEnabled="True"
ItemClick="categoryItemsGV_ItemClick"
SelectionMode="Single"
ItemsSource="{Binding}">
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<!--<Setter Property="VerticalContentAlignment" Value="Center"/>-->
</Style>
</GridView.ItemContainerStyle>
<GridView.ItemTemplate>
<DataTemplate>
<Grid Width="195" Height="43" Margin="3">
<StackPanel Width="193" Height="40" Background="Gray" Opacity="0.5" HorizontalAlignment="Right" VerticalAlignment="Bottom" />
<StackPanel Orientation="Horizontal" Width="193" Height="40" Padding="7,7,0,0" Background="#FDFCC2" HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBlock Text="{Binding ProductOptionLineName}" FontSize="18" MaxLines="1" TextTrimming="CharacterEllipsis" Visibility="{Binding Converter={StaticResource langToVisibilityConverter}, ConverterParameter='CH', Mode=OneWay}">
</TextBlock>
<TextBlock Text="{Binding ProductOptionLineNameEn}" FontSize="18" MaxLines="1" TextTrimming="CharacterEllipsis" Visibility="{Binding Converter={StaticResource langToVisibilityConverter}, ConverterParameter='EN', Mode=OneWay}"/>
<TextBlock Text="{Binding ExtraPriceString}" FontSize="18" Margin="2,0,0,0"></TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
private async void categoryItemsGV_ItemClick(object sender, ItemClickEventArgs e)
{
var item = e.ClickedItem as ProductOptionLineModel;
}
We can use the SelectRange(ItemIndexRange) method to selects a block of items described by the ItemIndexRange.
When you call SelectRange(ItemIndexRange), all items in the specified range are selected, regardless of their original selection state. You can select all items in a collection by using an ItemIndexRange with a FirstIndex value of 0 and a Length value equal to the number of items in the collection.
For more info, see Remarks of the SelectRange(ItemIndexRange).
We can use the ItemClick to get which item is be clicked. Then we can add the SelectionChanged event and set the number of the clicked item to the SelectRange method.
For example:
private int number;
private void categoryItemsGV_ItemClick(object sender, ItemClickEventArgs e)
{
var item = e.ClickedItem as ProductOptionLineModel;
number = ProductOptionLineModels.IndexOf(item);
}
private void categoryItemsGV_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
categoryItemsGV.SelectRange(new ItemIndexRange(number, 1));
}
If we want to keep item selected as it was already selected, use below approach.
private async void categoryItemsGV_ItemClick(object sender, ItemClickEventArgs e)
{
var item = e.ClickedItem as ProductOptionLineModel;
GridView gv = sender as GridView;
gv.SelectedItems.Remove(item);
}
and if we want to keep item deselect on click (prevent deselected) for validation purpose. used below approach.
private async void categoryItemsGV_ItemClick(object sender, ItemClickEventArgs e)
{
var item = e.ClickedItem as ProductOptionLineModel;
await _viewModel.DialogService("FirstRequireMinOption", "", true);
GridView gv = sender as GridView;
gv.SelectedItems.Add(item);
}
I am trying to detect which item in a listview is focused, but I am not getting the events detected. I am developing for Xbox One UWP, so I cannot use mouse or keyboard events, only focus can be used.
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" GotFocus="StackPanel_GotFocus" >
<StackPanel Name="Imagestack" Orientation="Horizontal">
<Image Source="{Binding Image}" Height="144" Width="256" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
private void StackPanel_GotFocus(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Image focus");
Image img = sender as Image;
Bgimage.Source = img.Source;
}
You should register to the ListView.GotFocus event.
The OriginalSource from the event parameter will be the ListViewItem which has received the focus. You can then retrieve the item content using ListViewItem.Content.
XAML:
<ListView x:Name="list" GotFocus="list_GotFocus">
<ListView.ItemTemplate>...</ListView.ItemTemplate>
</ListView>
Code behind:
private void list_GotFocus(object sender, RoutedEventArgs e)
{
var focusedItem = (e.OriginalSource as ListViewItem)?.Content;
}
You don't need to get focus state to get data from the clicked ListViewItem, the ItemClick event of the ListView may be what you're looking for:
<ListView x:Name="LV_Items"
IsItemClickEnabled="True"
ItemClick="LV_Items_ItemClick"
>
</ListView>
private void LV_Items_ItemClick(object sender, ItemClickEventArgs e)
{
// Get instance of the model in the clicked ListViewItem
MyModel myModel = (MyModel)e.ClickedItem;
Image img = myModel.Image;
}
I am building a WPF application with MVVM architecture. In one form I have 2 listboxes and I want to perform filter based search. I am using a common search textbox, so I have to differentiate the search based on which listbox is selected. Please find my sample listbox below:
<HeaderedContentControl Header="Visible Objects:" Height="120" Width="250" Margin="20,20,20,0">
<ListBox Name="lstObjects" Height="100" Margin="5" ItemsSource="{Binding ProfileObjTypeToBind, Mode=OneWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Name="chkbxVisibleObjects" Grid.Column="1"
Content="{Binding Path=Value}" IsChecked="{Binding Path=flag,Mode=TwoWay}">
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</HeaderedContentControl>
<HeaderedContentControl Header="User Groups to View:" Height="120" Width="250" Margin="20,10,20,10">
<ListBox Name="lstGroups" Height="100" Margin="5" ItemsSource="{Binding ProfileUserGrpToBind, Mode=OneWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Name="chkAllowedGroups" Content="{Binding Path=GroupName}"
IsChecked="{Binding Path=flag,Mode=TwoWay}">
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</HeaderedContentControl>
All I want to do is identify the listbox selected and perform the filtering based on text entered in textbox. Please help me
Thanks a lot in advance.
You can't have a selected ListBox AND be able to write stuff to a TextBox. You can save the reference to your last ListBox though using SelectionChanged or some other method
private ListBox SelectedListBox = null;
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SelectedListBox = (sender as ListBox);
}
once you have a reference to your last selected ListBox you can add TextChanged event to your TextBox:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (SelectedListBox == null)
return;
string searchText = (sender as TextBox).Text;
SelectedListBox.Items.Filter = (i) => { return ((string)i).Contains(searchText); }; // Or any other condition required
}
I have a StackPanel. The contents of the StackPanel are defined in a Data Template and they are basically another StackPanel composed of two Buttons and two Text Blocks. Now... when I touch the StackPanel I can get the element I touched through
e.TouchDevice.DirectlyOver
Where e is a TouchEventArgs variable. But I can only get the actual UIElement... I'm intrested in getting the index of the element of the StackPanel that I touched.
Anyone knows how to do that?
Thank you.
XAML:
<DataTemplate x:Key="AddBookListTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="9.9*"/>
<ColumnDefinition Width="0.1*"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" >
<StackPanel Orientation="Horizontal">
<Button blabla>
</Button>
<Button blabla>
</Button>
</StackPanel>
<TextBlock/>
<TextBlock/>
</StackPanel>
</Grid>
</DataTemplate>
And is reused
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Books}" Margin="0 10 0 0" Background="Transparent" ItemTemplate="{StaticResource AddBookListTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" TouchEnter="StackPanel_TouchEnter"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
You could simply use the IndexOf method on the panel's Children collection:
private void panel_Touch(object sender, RoutedEventArgs e)
{
MessageBox.Show("You've touched n°" + panel.Children.IndexOf(sender as UIElement));
}
You could use VisualTreeHelper to walk up the visual tree, and then use IndexOf() to get the index:
private void panel_Touch(object sender, RoutedEventArgs e)
{
int index;
var button = sender as Button;
if (button != null)
{
var contentPresenter = VisualTreeHelper.GetParent(button) as ContentPresenter;
if (contentPresenter != null)
{
var stackPanel = VisualTreeHelper.GetParent(contentPresenter) as StackPanel;
if (stackPanel != null)
index = stackPanel.Children.IndexOf(contentPresenter);
}
}
}
Use a tool like Snoop to view the visual treee so you know what types to expect (I think that StackPanel puts ContentPresenters around each item, but I could be wrong).
It's a bit of a hack though. I'd recommend something more like this:
<StackPanel Orientation="Horizontal">
<Button Content="OK" Command="{Binding OKCommand}" />
<Button Content="Cancel" Command="{Binding CancelCommand}" />
</StackPanel>
Where OKCommand and CancelCommand are RelayCommands on your ViewModel.
I created a LongListSelector with textblock and an image,then How do I tap the image to show selected item name in my list, and tap the item name to show messagebox? Below is my code to bind the name and image:
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="TileDataTemplate">
<Grid Background="{StaticResource TransparentBrush}"
Margin="0, 0, 0, 12" Height="60">
<TextBlock Text="{Binding Name}" Margin="60, 10, 0, 0" FontSize="24" Height="60">
</TextBlock>
<Image x:Name="GetName" Tap="GetName_Tap" Grid.Column="0" Source="/Assets/AppBar/Delete.png" Height="40" Width="40"
Margin="0, 6, 0, 5" HorizontalAlignment="Right" VerticalAlignment="Top" />
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<phone:LongListSelector
SelectionChanged="MainLongListSelector_SelectionChanged"
Margin="10,6,0,0"
ItemsSource="{Binding Staff.Items}"
LayoutMode="Grid"
GridCellSize="400,80"
ItemTemplate="{StaticResource TileDataTemplate}"
/>
</Grid>
Code Behind:
private void MainLongListSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
MessageBox.Show("Hi");
}
private void GetName_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
LongListSelector selector = sender as LongListSelector;
StaffData data = selector.SelectedItem as StaffData;
MessageBox.Show(data.Name);
}
When I tap on textblock,the message "Hi" is displayed successful. But if I tap on image, I get the null value. How to I solve it? Thanks
sender isn't the LongListSelector but the image on which the user tapped, hence the null error.
Basically, you just want to retrieve the item on which the user has tapped? In that case, use the DataContext property of the tapped control to retrieve it:
private void GetName_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
var element = (FrameworkElement)sender;
StaffData data = (StaffData)element.DataContext;
MessageBox.Show(data.Name);
}
(FrameworkElement is the base type of every UI control. Using that, you don't have to worry about whether it's an image, a textblock, ...)