Xamarin - clearing ListView selection - c#

I am actually working with this piece of code
using System;
using Xamarin.Forms;
using System.Diagnostics;
namespace CryptoUI
{
public class HomePage : Xamarin.Forms.MasterDetailPage
{
public HomePage()
{
// Set up the Master, i.e. the Menu
Label header = new Label
{
Text = "MENU",
Font = Font.SystemFontOfSize(20, FontAttributes.Bold),
HorizontalOptions = LayoutOptions.Center
};
// create an array of the Page names
string[] myPageNames = {
"Main",
"Page 2",
"Page 3",
};
// Create ListView for the Master page.
ListView listView = new ListView
{
ItemsSource = myPageNames,
};
// The Master page is actually the Menu page for us
this.Master = new ContentPage
{
Title = "Test",
Content = new StackLayout
{
Children =
{
header,
listView
},
}
};
// Define a selected handler for the ListView contained in the Master (ie Menu) Page.
listView.ItemSelected += (sender, args) =>
{
// Set the BindingContext of the detail page.
this.Detail.BindingContext = args.SelectedItem;
string currentPage = this.GetType().Name.ToString();
// This is where you would put your “go to one of the selected pages”
if(listView.SelectedItem.Equals("Main") && !currentPage.Equals("HomePage")){
AsyncPush(new HomePage());
}
else if(listView.SelectedItem.Equals("Page 2") && !currentPage.Equals("SecondPage")){
AsyncPush(new SecondPage());
}
else if(listView.SelectedItem.Equals("Page 3") && !currentPage.Equals("ThirdPage")){
AsyncPush(new ThirdPage());
}
// Show the detail page.
this.IsPresented = false;
};
listView.ItemSelected += (senders, e) => {
if (e.SelectedItem == null) return; // don't do anything if we just de-selected the row
// do something with e.SelectedItem
((ListView)senders).SelectedItem = null; // de-select the row
};
// Set up the Detail, i.e the Home or Main page.
Label myHomeHeader = new Label
{
Text = "Home Page",
HorizontalOptions = LayoutOptions.Center
};
string[] homePageItems = { "Alpha", "Beta", "Gamma" };
ListView myHomeView = new ListView {
ItemsSource = homePageItems,
};
var myHomePage = new ContentPage();
myHomePage.Content = new StackLayout
{
Children =
{
myHomeHeader,
myHomeView
} ,
};
this.Detail = myHomePage;
}
public async void AsyncPush(Page page)
{
await Navigation.PushAsync(page);
}
}
}
This code actually shows an easy FlyOut menu, using the Xamarin Forms technologies.
I am currently trying to understand how I could easily clear the ListView selection after I have selected which page I want to head to!
I found this piece of code on Xamarin's website for devs (http://developer.xamarin.com/guides/cross-platform/xamarin-forms/working-with/listview/);
listView.ItemSelected += (sender, e) => {
if (e.SelectedItem == null) return; // don't do anything if we just de-selected the row
// do something with e.SelectedItem
((ListView)sender).SelectedItem = null; // de-select the row
};
But I can't currently figure out how I should integrate it with my code above there :)

I would like to add to Jason's answer because it misses some vital information. When you set the ListView SelectedItem property to null, it will fire off the ItemSelected event again. So if you do not have a null check, it will throw an exception.
This is what it should look like:
void ItemSelected(object sender, EventArgs args)
{
if (((ListView)sender).SelectedItem == null)
return;
//Do stuff here with the SelectedItem ...
((ListView)sender).SelectedItem = null;
}

You're assigning the ItemSelected handler twice, which is a bad idea. All you should have to do is add this line to your existing ItemSelected handler
((ListView)sender).SelectedItem = null;

I had this same problem but the other solutions did not work for me. Since I needed to pass a custom object to the next page I nullified the selected item reference and used the item tapped reference for my custom object.
listView.ItemTapped += async (sender, e) =>{
await Navigation.PushAsync(new DetailPage(e.Item as CustomObject));
((ListView)sender).SelectedItem = null;
};

ListView.SelectedItem does not have setter (I mean simple Xamarin Android - not Xamarin.Forms). I suggest to use the following code:
private void DeselectEntities()
{
if (this.listView != null && this.listView.CheckedItemPositions != null)
{
this.listView.CheckedItemPositions.Clear();
}
}

I respect all given answers but in an MVVM app you'd better avoid too much code behind. What I usually do is following:
Bind ItemsSource of ListView as usual to an ObservableCollection where T is a CarViewModel in my case
Set SelectionMode="None": This does avoid the selection of SelectedItem on tap
Use EventToCommandBehavior (I use my own implementation; see github.com or use the one from Prism.Forms) to bind ItemTapped event of ListView to my ViewModel command SelectedCarChangedCommand.
In the ViewModel's SelectedCarChangedCommand you'll receive the tabbed item as ItemTappedEventArgs object.
<ListView
x:Name="CarsListView"
ItemsSource="{Binding Cars}"
SelectionMode="None">
<ListView.Behaviors>
<behaviors:EventToCommandBehavior
Command="{Binding SelectedCarChangedCommand}"
EventName="ItemTapped" />
</ListView.Behaviors>

Related

How can you capture UWP pointer events on Popups/Tooltips/TeachingTip

I'm using UWP's TeachingTip and I need to know when the pointer is over the control.
This is how I create and insert the TeachingTip:
var teachingTip = new TeachingTip
{
IsOpen = true,
Title = "hello",
Subtitle = "world"
};
var mainPage = (Window.Current.Content as Frame)?.Content as MainPage;
var content = (Windows.UI.Xaml.Controls.Canvas)mainPage.Content;
content.Children.Add(teachingTip);
I tried this but didn't get any event:
teachingTip.PointerEntered += TipPointerEntered;
teachingTip.PointerExited += TipPointerExited;
...
I also tried this but that didn't make any difference:
teachingTip.AddHandler(UIElement.PointerEnteredEvent, new PointerEventHandler(TipPointerEntered), true);
Then i read here this:
If you want to handle routed events from a Popup or ToolTip, place the handlers on specific UI elements > that are within the Popup or ToolTip and not the Popup or ToolTip elements themselves.
So my best guess is that a TeachingTip behaves the same. But I couldn't figure out how to gain access to the TeachingTip's children.
So I tried a different approach, maybe I could track the pointer once the tip is open and do some hit testing on the control. So I tried this:
var mainPage = (Window.Current.Content as Frame)?.Content as MainPage;
mainPage.AddHandler(UIElement.PointerMovedEvent, new PointerEventHandler(PointerMoved), true);
void PointerMoved(object sender, PointerRoutedEventArgs e)
{
var page = (Window.Current.Content as Frame)?.Content as MainPage;
var currPoint = e.GetCurrentPoint(page);
var elements = VisualTreeHelper.FindElementsInHostCoordinates(new Windows.Foundation.Point(currPoint.Position.X, currPoint.Position.Y), teachingTip);
foreach (UIElement element in elements)
{
// Eureka! found an element
}
}
but no eureka... if anyone can help...
Eventually I revisited this (a couple of years later...).
The solution is pretty simple, after applying a template you need to get the root element on which you want to register for pointer positions, like this:
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
var rootGrid = this.GetTemplateChild("ContentRootGrid") as Windows.UI.Xaml.Controls.Grid;
if (rootGrid != null)
{
rootGrid.PointerEntered += (sender, e) =>
{
SetPointerPosition(PointerPosition.Popup);
};
rootGrid.PointerExited += (sender, e) =>
{
SetPointerPosition(PointerPosition.Page);
};
}
}

How to make some ListView items 'greyed-out' and unselectable?

Some items in the ListView control will be selectable and have normal text.
Some items however, although included in the ListView as items, will be unselectable/unclickable and 'greyed-out'.
In Windows-Store-Apps we have the ability to select Single/Multiple/None items in a ListView. But how can make certain items at certain indexes unselectable/unclickable and 'greyed-out', in code mainly?
I managed to access the Item of the ListView at a certain index:
myListView.ItemContainerGenerator.ContainerFromIndex(i)
But I couldn't find any option to customize its selected event handler.
Any idea how to achieve that?
In Single selection mode.
First Add a boolean property to class of binding type which defines which items are clickable like this
class TestClass
{
Boolean IsClickAllowed{get;set;}
string name{get;set;}
}
then create a source list of TestClass type and set it as itemssource of Listview like this
var TempList=new List<>()
{
new TextClass(){IsClickAllowed=false,name="First Item"},
new TextClass(){IsClickAllowed=true,name="Second Item"},
new TextClass(){IsClickAllowed=false,name="Third Item"},
};
MyList.ItemsSource=TempList;
and for greying out Set Different DataTemplate for nonClickable items implementing DataTemplateSelector and finally for click handle in ItemClick event. You need to set IsItemClickEnabled as true.
private void MyList_ItemClick(object sender, ItemClickEventArgs e)
{
var item = e.ClickedItem as TestClass;
if (item != null){
if(item.IsClickAllowed){
//Do Stuff here
}else
{
//Do Nothing
}
}}
Hope it helps.
I have found a solution:
I have override the ListView control and create a StripedListView. Then by overriding the PrepareContainerForItemOverride, which is responsible for the setting up the ListViewItem control after it’s be created, you could modify the background color and set the ItemListView.isEnabled option to false:
public class StripedListView : ListView
{
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
var listViewItem = element as ListViewItem;
if (listViewItem != null)
{
var index = IndexFromContainer(element);
if (Words.arrayW[index].Length > 0)
{
listViewItem.Foreground = new SolidColorBrush(Colors.Black);
}
else
{
listViewItem.Foreground = new SolidColorBrush(Colors.Gray);
listViewItem.IsEnabled = false;
}
}
}
}
In Xaml:
<controls:StripedListView x:Name="letterListView" ItemsSource="{Binding}">
<controls:StripedListView.ItemTemplate>
<DataTemplate>
etc...
</DataTemplate>
</controls:StripedListView.ItemTemplate>
</controls:StripedListView>

Problems with Syncfusion GridTreeControl and Binding

I'm new to WPF and am using the Syncfusion Framework. I want to use the DataTreeControl to display a hierarchy of data which will be loaded and updated in a reoccuring interval. But for some reason it doesn't display the data.
Here's a snipped from my MainWindow.xaml
<syncfusion:TabItemExt Name="_tabItemTipps" Header="Tipps">
<syncfusion:GridTreeControl Name="_treeGrid"
BorderBrush="LightGray"
BorderThickness="0,0.5,0,0"
EnableHotRowMarker="False"
EnableNodeSelection="True"
ExpandStateAtStartUp="AllNodesExpanded"
ReadOnly="True"
SupportNodeImages="True"
VisualStyle="Metro"
ItemsSource="SoccerMarkets"
>
<!-- Code for GridTreeControl Columns -->
<syncfusion:GridTreeControl.Columns>
<syncfusion:GridTreeColumn HeaderText="Nation" MappingName="{Binding RoughCat}"></syncfusion:GridTreeColumn>
</syncfusion:GridTreeControl.Columns>
</syncfusion:GridTreeControl>
This the snippet from MainWindow.xaml.cs where the DataContext is set:
public MainWindow()
{
DataContext = this;
InitializeComponent();
SkinStorage.SetVisualStyle(_tabControl, "Metro");
_settingsVM = new AppSettingsVM();
_txtBetdaqUser.DataContext = _settingsVM;
_chkSystemActive.DataContext = _settingsVM;
_chkInSimulationMode.DataContext = _settingsVM;
_mechanic = new TippMechanic(_settingsVM);
_soccerMarketsVM = new SoccerMarketVM();
Task[] tasks = new Task[1];
tasks[0] = Task.Factory.StartNew(async () => await _mechanic.Init());// _mechanic.Init();
Task.WaitAll(tasks);
_soccerMarketsVM.SoccerMarkets = _mechanic.SoccerMarketManager.SoccerMarkets;
_treeGrid.DataContext = _soccerMarketsVM.SoccerMarkets;
}
My ViewModel (_soccerMarketsVM) is defined this way:
class SoccerMarketVM : ObservableObject
{
private ObservableCollection<SoccerMarket> _soccerMarkets;
public ObservableCollection<SoccerMarket> SoccerMarkets
{
get { return _soccerMarkets; }
set
{
if(_soccerMarkets != null)
_soccerMarkets.CollectionChanged -= _soccerMarkets_CollectionChanged;
_soccerMarkets = value;
_soccerMarkets.CollectionChanged += _soccerMarkets_CollectionChanged;
}
}
public SoccerMarketVM()
{
//_soccerMarkets = new ObservableCollection<SoccerMarket>();
//_soccerMarkets.CollectionChanged += _soccerMarkets_CollectionChanged;
}
void _soccerMarkets_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Console.WriteLine(e.Action.ToString());
}
}
The Events for CollectionChanged are fired and I get the Console.Writeline output.
Does anyone see's something wrong here?
In GridTreeControl, you can populate the data using different ways. In your code snippet, ItemsSource defined without specifying the Binding keyword and the MappingName is defined with Binding keyword. But for itemssource, you need to specify binding and for mapping name, you can directly assign property name without specifying binding. Please refer the below UG link of data population in GridTreeControl,
Link:
http://help.syncfusion.com/ug/wpf/index.html#!Documents/addingthegridtreecontroltoawpfapplication.htm
Elavarasan M – Syncfusion Software.

C# ListView from Another Function

Please forgive me for such a stupid question. I am sure many of you will find this easy, where I have sent almost half the day reading trying to figure this out.
Here is the problem:
I have a FORM (Form1.cs) made. In that form I created a listview, and named it "ListView1".
Within the Form1.cs, I call a function called FileManager(this), where I pass in the THIS object.
In FileManager.cs I was able to listviewArray= originalForm.Controls.Find("listView1", true) and find that 'listview'.
When I do a listviewArray[0]<-- I can't seem to add a list to it.
FileManager.cs
FileManager(object sender)
{
if (sender != null)
{
originalForm = (Form)sender;
}
}
public void getFiles()
{
filePaths = Directory.GetFiles(hsocDir);
if(filePaths != null)
{
listviewArray= originalForm.Controls.Find("listView1", true);
if(listviewArray != null)
{
ListViewItem lvi = new ListViewItem("text");
// My Array is listViewArray
// How to add things to Lvi to it.
}
}
== Form1.cs
public Form1()
{
InitializeComponent(`enter code here`);
mysql = new MySQLCheck(this);
fileManager = new FileManager(this);
fileManager.getFiles();
}
You can't access element 0 of the collection because the collection is empty. To add an item, use:
listViewArray.Items.Add(lvi);
You need to modify the Items collection instead of the ListView itself for this to work, as ListView is not a collection (its a control).
listViewArray.Items.Add(lvi);
Also in your listview,setting this properties will help :
// Set the view to show details.
listViewArray.View = View.Details;
// Select the item and subitems when selection is made.
listViewArray.FullRowSelect = true;
// Display grid lines.
listViewArray.GridLines = true;

C# listView Blink/Alternative Color

Is it possible to animate ListView items in C# ? The purpose is that I have a ListView that is asynchronously modified, and I'd like to animate smoothly the items that have been modified, until the user clicks them. This way items blinking, or whatever would do the trick, are the items that changed which haven't been reviewed yet.
Thank you guys !
UPDATE : sorry, i forgot. Never used WPF before, and I think it's too late to switch to it now. I'm using winforms.
I had to do something similar to what you are trying to do but instead of animating the ListView, I used custom checkbox layout in the list view to look different. The designer code for the ListView looks like:
this.listView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
this.listView1.Location = new System.Drawing.Point(104, 90);
this.listView1.MultiSelect = false;
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(264, 105);
this.listView1.Sorting = System.Windows.Forms.SortOrder.Ascending;
this.listView1.TabIndex = 7;
this.listView1.UseCompatibleStateImageBehavior = false;
this.listView1.View = System.Windows.Forms.View.Details;
this.listView1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.listView1_MouseClick);
Then I declared a list that will hold the selection of the user.
private IList<ListViewItem> m_CheckedItems = new List<ListViewItem>();
Here is the initialise method for the ListView. You need to manipulate here for the initial look of your listview.
private void InitialiseListView(IList<string> data)
{
listView1.Items.Clear();
m_CheckedItems.Clear();
listView1.Columns.Clear();
listView1.Columns.Add("Col1");
listView1.Columns[0].Width = listView1.Width;
ListView.ListViewItemCollection collection = new ListView.ListViewItemCollection(listView1);
ImageList images = new ImageList();
images.Images.Add(global::MyApplication.Properties.Resources.Checkbox_Unchecked);
images.Images.Add(global::MyApplication.Properties.Resources.Checkbox_Checked);
listView1.SmallImageList = images;
foreach (string str in data)
{
ListViewItem item = new ListViewItem();
item.ImageIndex = 0;
item.Text = str;
collection.Add(item);
}
}
This event triggers when the user selects an option in the list view. The selection is recorded in the list I created above and the checked image is displayed so that it looks like the user has selected the item.
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && listView1.FocusedItem != null)
{
if (listView1.FocusedItem.ImageIndex == 1)
{
listView1.FocusedItem.ImageIndex = 0;
m_CheckedItems.Remove(listView1.FocusedItem);
}
else
{
listView1.FocusedItem.ImageIndex = 1;
m_CheckedItems.Add(listView1.FocusedItem);
}
}
}
You can probably fiddle with fonts and forecolor of these items ... Each item within a List View is of type ListViewItem so you can individually manipulate it.
Hope this gives you some direction :)
You could use a MyListView: ListView and override OnDrawSubItem. Have the e.Item.Tag to store the "Clicked" state and update the background according to its state.
public partial class ObjectListView : ListView {
(....)
protected override void OnDrawSubItem(DrawListViewSubItemEventArgs e)
{
if(bool)e.Item.Tag)
(...) animate
}
You can do that easier in WPF.
WPF Basic
http://msdn.microsoft.com/en-us/library/ms754130.aspx
http://en.wikipedia.org/wiki/Windows_Presentation_Foundation
WPF Animation
http://msdn.microsoft.com/en-us/library/ms752312.aspx
ListView animation sample
(WPF) Animate ListView item move
WPF ListView animation by reorder of items?

Categories

Resources