UPDATE: I think implementing it with a Custom Renderer which customizes ListView is the approach. I'll post back with results.
I'm trying to implement a multi-select list. The list only contains a list of one type of cell. If I'm not mistaken, the ListView only allows for single select and can't be subclassed to override that, and so I'm trying to use the TableView with Intent.Data but the documentation is sparse and I can't really figure out how to. What is the best approach? Should I use a Custom Renderer ?
Here's 2 videos about creating a toggle button. This should get you half way there with creating a decent looking multi select list.
the ToggleButton class
public class ToggleButton : Button { #region BindableProps public static readonly BindableProperty SelectedProperty = BindableProperty.Create<ToggleButton, bool>(p => p.Selected, default(bool)); public bool Selected { get { return (bool)GetValue(SelectedProperty); } set { SetValue(SelectedProperty, value); } } public static readonly BindableProperty SelectedTextColorProperty = BindableProperty.Create<ToggleButton, Color>(p => p.SelectedTextColor, default(Color)); public Color SelectedTextColor { get { return (Color)GetValue(SelectedTextColorProperty); } set { SetValue(SelectedTextColorProperty, value); } } public static readonly BindableProperty SelectedBackgroundColorProperty = BindableProperty.Create<ToggleButton, Color>(p => p.SelectedBackgroundColor, default(Color)); public Color SelectedBackgroundColor { get { return (Color)GetValue(SelectedBackgroundColorProperty); } set { SetValue(SelectedBackgroundColorProperty, value); } } public static readonly BindableProperty DeSelectedTextColorProperty = BindableProperty.Create<ToggleButton, Color>(p => p.DeSelectedTextColor, default(Color)); public Color DeSelectedTextColor { get { return (Color)GetValue(DeSelectedTextColorProperty); } set { SetValue(DeSelectedTextColorProperty, value); } } public static readonly BindableProperty DeSelectedBackgroundColorProperty = BindableProperty.Create<ToggleButton, Color>(p => p.DeSelectedBackgroundColor, default(Color)); public Color DeSelectedBackgroundColor { get { return (Color)GetValue(DeSelectedBackgroundColorProperty); } set { SetValue(DeSelectedBackgroundColorProperty, value); } } #endregion private void setColors() { if (this.Selected) { this.TextColor = SelectedTextColor; this.BackgroundColor = SelectedBackgroundColor; } else { this.TextColor = DeSelectedTextColor; this.BackgroundColor = DeSelectedBackgroundColor; } } public ToggleButton() { this.Clicked += (sender, e) => { this.Selected = !this.Selected; }; this.BorderRadius = 0; this.BorderWidth = 0; } protected override void OnPropertyChanged(string propertyName = null) { base.OnPropertyChanged(propertyName); List<string> propNames = new List<string> { ToggleButton.SelectedProperty.PropertyName, ToggleButton.SelectedBackgroundColorProperty.PropertyName, ToggleButton.DeSelectedBackgroundColorProperty.PropertyName, ToggleButton.SelectedTextColorProperty.PropertyName, ToggleButton.DeSelectedTextColorProperty.PropertyName }; if (propertyName != null && propNames.Contains(propertyName)) { setColors(); } } }
the page definition
public static Page GetMainPage() { ContentPage page = new ContentPage(); StackLayout layout = new StackLayout(); Label countLabel = new Label { Text = "Count: 0" }; ScrollView scrollLayout = new ScrollView(); StackLayout buttonLayout = new StackLayout(); List<ToggleButton> buttons = new List<ToggleButton>(); for (int i = 0; i < 50; i++) { ToggleButton button = new ToggleButton { Selected = false, Text = "Button " + i, DeSelectedBackgroundColor = Color.White, DeSelectedTextColor = Color.Black, SelectedBackgroundColor = Color.Black, SelectedTextColor = Color.White, }; button.Clicked += (sender, e) => { countLabel.Text = "Count: " + buttons.Where(b => b.Selected == true).Count().ToString(); }; buttonLayout.Children.Add(button); buttons.Add(button); } page.Content = layout; layout.Children.Add(countLabel); layout.Children.Add(scrollLayout); scrollLayout.Content = buttonLayout; return page; }
Not sure I answered the original question... hopefully some of this would be useful.
I didn't realize how loud my keyboard was! ha. I need a microphone and some decent screen casting software.
Also a bit random, but here's my bindable property snippet
<?xml version="1.0" encoding="utf-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <SnippetTypes> <SnippetType>Expansion</SnippetType> </SnippetTypes> <Title>bprop</Title> <Author>Microsoft Corporation</Author> <Description>Code snippet for an automatically implemented $name$Property Language Version: C# 3.0 or higher</Description> <HelpUrl> </HelpUrl> <Shortcut>bprop</Shortcut> </Header> <Snippet> <Declarations> <Literal Editable="true"> <ID>name</ID> <ToolTip>name</ToolTip> <Default>name</Default> <Function> </Function> </Literal> <Literal Editable="true"> <ID>owner</ID> <ToolTip>owner</ToolTip> <Default>Owner</Default> <Function> </Function> </Literal> <Literal Editable="true"> <ID>type</ID> <ToolTip>type</ToolTip> <Default>Type</Default> <Function> </Function> </Literal> </Declarations> <Code Language="csharp"><![CDATA[public static readonly BindableProperty $name$Property = BindableProperty.Create<$owner$,$type$>(p => p.$name$, default($type$)); public $type$ $name$ { get { return ($type$)GetValue($name$Property); } set { SetValue($name$Property, value); } }$end$]]></Code> </Snippet> </CodeSnippet> </CodeSnippets>
@RyanHatfield, @PatrickKealy:
Hi all
For your informaton:
I have posted my solution for a (simple) "multiselect ListView" here:
forums.xamarin.com/discussion/17885/multiselect-listviews#latest
Answers
Did u have any luck? Mine is the same problem! please share if u got the multi select list working...
I had to put this aside because I ran out of time but extending the ListView wasn't possible due to the inability to override the single selection behavior it encapsulates. If the accessors change in a future version then it might be possible but otherwise I think mapping a CustomRenderer to a UITableView that is setup for multi-select would be the approach.
Anyone else get this going?
does it have to be a cell?
You could render a list of buttons, \
And set the button command to toggle the colors of the button. when you're done, use some linq on the buttonList and you can figure out what's selected. Something like:
This can all be done in top level Xamarin.Forms without custom renders. If you're interested I could probably whip up an example of what I mean. I've done it in a recent project (Podio integration) but it's waaaaay too involved to dig out. I'd rather make something clean from scratch.
That sounds way easier, but I thought that you have to use cells with the list. Also are there any performance issues? If it isn't a cell how is the queue/dequeue reusable cell mechanism working? I'd be interested to see the example. If it works fine I'd be pretty happy with this.
Here's 2 videos about creating a toggle button. This should get you half way there with creating a decent looking multi select list.
Part1
Part2
the ToggleButton class
the page definition
Not sure I answered the original question... hopefully some of this would be useful.
I didn't realize how loud my keyboard was! ha. I need a microphone and some decent screen casting software.
Also a bit random, but here's my bindable property snippet
This is simply great and surely helpful for someone like me looking for a quick alternative to implement a multiselect list. Thanks for support and time.
@RyanHatfield, @PatrickKealy:
Hi all
For your informaton:
I have posted my solution for a (simple) "multiselect ListView" here:
forums.xamarin.com/discussion/17885/multiselect-listviews#latest