Get focused list item in a ListView with SelectionMode=None - win-universal-app

I have a list like this:
<ListView x:Name="MyList" SelectionMode="None" KeyDown="MyList_KeyDown">
<ListView.Items>
<x:String>Alfa</x:String>
<x:String>Beta</x:String>
<x:String>Gamma</x:String>
</ListView.Items>
</ListView>
In the key down event I want to know which item that is in focus. But since SelectionMode is none, SelectedItem is null. Is there some way to solve this?

You can try something like this:
private void MyList_KeyDown(object sender, KeyRoutedEventArgs e)
{
var inFocus = FocusManager.GetFocusedElement() as ListViewItem;
if(inFocus?.Content != null)
{
//Selected data is now in inFocus.Content
}
}

Related

multiple selection on custom picker C# UWP

I've been looking on forums and internet about a custom picker on C#, I have a picker already functional, but some of my research throw me that you are only able to select 1 item of the custom Picker, this is the code im using to deploy the picker.
Picker
<custom:CustomPicker x:Name="pickerCategories" ItemsSource="{Binding listCategoriesName}" SelectedIndex="{Binding SelectedCategory}" SelectedIndexChanged="pickerCategories_SelectedIndexChanged" Grid.Column="1" BackgroundColor="White"/>
the item source are given to the picker as a list of object from a database
is there a way to be able to select multiple index of the custom picker?
for Example...
Picker pk = new Picker(); pk.SelectionMode=Multiple;
For you requirement, you could make a custom Picker renderer in the native uwp project. And then make a new DataTemplate for displaying ComboBox item that contain checkbox in the native control.
<DataTemplate x:Key="templateEmployee" >
<StackPanel Orientation="Horizontal">
<CheckBox Content="{Binding Content,Mode=TwoWay}" IsChecked="{Binding IsCheck,Mode=TwoWay}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</StackPanel>
</DataTemplate>
For CustomPickerRenderer, you should pass the Forms Picker item source to native control(ComboBox). And when combobox drop down closed, you could execute InvokeAction method to send Data to the Forms Picker.
public class CustomPickerRenderer : PickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
Control.ItemsSource = e.NewElement.ItemsSource;
Control.ItemTemplate = (Windows.UI.Xaml.DataTemplate)App.Current.Resources["templateEmployee"];
Control.DropDownClosed += Control_DropDownClosed;
}
private void Control_DropDownClosed(object sender, object e)
{
var NewElement = Element as CustomPicker;
var items = (sender as ComboBox).ItemsSource;
NewElement.InvokeAction(items);
}
}
Usage
public MainPage()
{
InitializeComponent();
MyPicker.ItemsSource = new MainViewModel().itemSource;
MyPicker.RegisterAction(IsCheckItems);
}
private List<Item> SelecItms = new List<Item>();
private void IsCheckItems(object data)
{
var items = data as ObservableCollection<Item>;
var str = new StringBuilder();
foreach (var item in items)
{
if (item.IsCheck)
{
SelecItms.Add(item);
str.AppendLine(item.Content);
}
}
SeleitemLabel.Text = str.ToString();
}
And I have uploaded the code sample. Please check.

Xamarin Forms Tags in CarouselView

I'm using the new CarouselView control in my app to display a collection of text/articles. Each article in the collection also contains a string array of text that I refer to as tags. I would like to display these tags horizontally within the carouselview using a control that allows databinding. The expected look should be something like this just below the main text:
Expected look of tags
Any ideas on how I could achieve this?
Well, first the good/bad news: the ListView would allow you to present a bindable set of tags, but unfortunately it does not currently support a Horizontal orientation, so it wouldn't meet your needs.
The next best thing would be a horizontal StackLayout contained within a ScrollView:
<ScrollView Orientation="Horizontal">
<StackLayout x:Key="tags" Orientation="Horizontal">
</StackLayout>
</ScrollView>
And populate that StackLayout with data from the ViewModel when the binding context or that property changes. The example below populates the StackLayout with Label views that are styled up using a style named "TagStyleName".
// Note: If this code doesn't work, someone else wrote it.
protected override OnBindingContextChanged() {
var vm = this.BindingContext as MyViewModelClass;
if (vm == null) return;
vm.PropertyChanged += (o, e) => {
if (e.PropertyName == "Tags") {
WatchTagsForChanges();
RefreshTags();
}
};
}
private void WatchTagsForChanges() {
var vm = this.BindingContext as MyViewModelClass;
if (vm == null) return;
vm.Tags.CollectionChanged += (o, e) => RefreshTags();
}
private void RefreshTags() {
var vm = this.BindingContext as MyViewModelClass;
if (vm == null) return;
this.tags.Children.Clear()
foreach (var tag in vm.Tags) {
this.tags.Children.Add(new Label{ Text = tag, Style = "TagStyleName" }));
}
}

How can I override or act on KeyDown: Space or Enter for ListView in UWP?

I've attached the KeyDown event to a ListView in my Win 10 UWP app. I want to make VirtualKey.Enter have a special effect, but the event is not firing for this particular key. Neither does it for Space, Arrow up or down. This I guess because the listview already has defined a special behaviour for those keys.
I'd like to override some of those keys though, or at least trigger additional actions. Even attaching events to those key with modifiers (e.g. Shift+ArrowDown) would not work because the events still are not firing.
I read that for WPF that there is a PreviewKeyDown-event which one can attach to. I can't find that event for UWP though. Are there any other options?
Stephanie's answer is a good one and it works in the general case. However, as Nilzor observed it will not work in the case of a ListView for the Enter key. For some reason the ListView handles the KeyDown event in case Enter is pressed.
A better way to handle key events when dealing with a ListView, as the question asks, is this.
private void ListView_Loaded(object sender, RoutedEventArgs e)
{
(sender as ListView).AddHandler(UIElement.KeyDownEvent, new KeyEventHandler(ListView_KeyDown), true);
}
private void ListView_KeyDown(object sender, KeyRoutedEventArgs args)
{
if (args.Key == Windows.System.VirtualKey.Enter)
{
}
}
Notice the last argument in the AddHandler function. This specifies whether we want to handle events already handled by a previous element in the visual tree.
Of course don't forget to unsubscribe from the event when appropriate
Here is one way to do it : subscribe to the global Window.Current.CoreWindow.KeyDown event.
Then save the focus state of your listview and react accordingly.
Here is the code :
public sealed partial class MainPage : Page
{
bool hasFocus = false;
public MainPage()
{
this.InitializeComponent();
Window.Current.CoreWindow.KeyDown += CoreWindow_KeyDown;
}
private void CoreWindow_KeyDown(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs args)
{
if(hasFocus)
{
Debug.Write("Key down on list");
}
}
private void myList_GotFocus(object sender, RoutedEventArgs e)
{
hasFocus = true;
}
private void myList_LostFocus(object sender, RoutedEventArgs e)
{
hasFocus = false;
}
You will also need to subscribe to the focus events in xaml, for your ListView :
<ListView .... GotFocus="myList_GotFocus" LostFocus="myList_LostFocus"/>
Corcus's solution doesn't work for me. What is working is handling PreviewKeyDown directly from XAML. Works well for SPACE or ENTER key:
XAML:
<ListView PreviewKeyDown="BookmarksListView_PreviewKeyDown">
Code behind:
private void BookmarksListView_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
// DO YOUR STUFF...
e.Handled = true;
}
}
You can use AddHandler method.
private void KeyEnterEventHandler(object sender, KeyRoutedEventArgs e)
{
if (e.OriginalKey == Windows.System.VirtualKey.Enter)
{
PlayFromListView();
}
}
private void LoadListView()
{
foreach (var music in playListStorageFile.PlayList)
{
ListViewItem item = new ListViewItem();
item.AddHandler(FrameworkElement.KeyDownEvent, new KeyEventHandler(KeyEnterEventHandler), true);
TextBlock mytext = new TextBlock();
mytext.Text = music.Nro.ToString() + " - " + music.Name;
mytext.Tag = music.Nro;
item.Content = mytext;
lvMusics.Items.Add(item);
}
}
https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.uielement.addhandler?view=winrt-18362

How to add or remove array item in windows phone?

Hi am using xaml file and code given below. I want to get two categories one is current categories and other one is removed categories.If i remove one category it should go to add current category.I don't have any idea about this.so please can any one tell me how to resolve this issue.
<StackPanel>
<TextBlock Text="Current categories"
Style="{StaticResource PhoneTextLargeStyle}"/>
<ListBox x:Name="AddingList" ItemsSource="{Binding name}" SelectionChanged="AddingList_SelectionChanged_1"/>
<TextBlock Text="Removed categories"
Style="{StaticResource PhoneTextLargeStyle}" />
<ListBox x:Name="RemoveList" ItemsSource="{Binding name}" SelectionChanged="RemoveList_SelectionChanged_1"/>
</StackPanel>
my xaml.cs code
private void Button_Click_1(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/CategoriesPage.xaml?" + NotchsList11, UriKind.Relative));
}
I am using edit button, How can i pass listbox item from edit button to categories page and how remove and add listbox items.
My out put want given below image so please help me some one
Few ways of going about this.
One way is to have a single object that has "isRemoved" boolean on it that you just turn on and off. Another way is you could have 2 observablecollections one holding the added, and one holding the removed. so for example:
class:
public class MyData
{
public bool isRemoved { get; set; }
public string Name { get; set; }
}
Use:
ObservableCollection<MyData> AllData = new ObservableCollection<MyData>()
AllData.Add(new MyData(){ isRemoved = true, Name = "Data1"}
AllData.Add(new MyData(){ isRemoved = true, Name = "Data2"}
AllData.Add(new MyData(){ isRemoved = false, Name = "Data3"}
AddingList.ItemsSource = AllData.Where(srch => srch.isRemoved == false);
RemoveList.ItemsSource = AllData.Where(srch => srch.isRemoved == true);
In your Remove button click you just set the isRemoved to true and in your Add you set the isRemoved to false.
or you could use 2 ObservableCollections adding and removing from each.

Preventing TabControl selection in Silverlight

Is there any way to prevent the change of a tab in TabControl in Silverlight 4?
A simple case is when I've got a form with some data, and I want to ask the user if he/she wants to save this data before actually changing the tab.
I've seen code examples on how to do this in WPF, but not in Silverlight.
What can I do to stop the tab from changing?
Bind SelectedIndex to a property on your data context.
<sdk:TabControl SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}">
<sdk:TabItem Header="TabItem">
<Grid Background="#FFE5E5E5"/>
</sdk:TabItem>
<sdk:TabItem Header="TabItem">
<Grid Background="#FFE5E5E5"/>
</sdk:TabItem>
</sdk:TabControl>
In the SET accessor, write your code to check whether the user really wants to do what they're trying to do.
public class Context : INotifyPropertyChanged
{
int _SelectedIndex = 0;
public int SelectedIndex
{
get
{
return _SelectedIndex;
}
set
{
MessageBoxResult result = MessageBox.Show("Do you want to save?", "Really?", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
{
_SelectedIndex = value;
}
RaisePropertyChanged("SelectedIndex");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
Net effect is, if the user chooses 'cancel' on the dialogue the private variable is never changed - the PropertyChanged event fires, rebinding the selected index to the existing value.
Hope this is what you were trying to accomplish.
UPDATE (11/10/2012) - Alternate method (possibly for SL5?). Write code behind to tie into SelectionChanged event of your TabControl, reset the tab control's selected item property based on your test.
private void TabControl_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (e.RemovedItems.Count > 0)
{
MessageBoxResult result = MessageBox.Show("Do you want to save?", "Really?", MessageBoxButton.OKCancel);
if (result != MessageBoxResult.OK)
{
((TabControl)sender).SelectionChanged -= new SelectionChangedEventHandler(TabControl_SelectionChanged);
((TabControl)sender).SelectedItem = e.RemovedItems[0];
((TabControl)sender).SelectionChanged += new SelectionChangedEventHandler(TabControl_SelectionChanged);
}
}
}

Resources