Xamarin bug-ish behaviour in CarouselView - CurrentItemChanged event fired unexpectedly? - c#

While I was trying to implement an infinite scroll page I've encountered a strange behaviour with the CurrentItemChanged event of Xamarin.Forms.CarouselView.
While the user scrolls, new items are added to the ItemSource and old items are removed (for low memory consumption).
After I encountered the strange behaviour I've debugged and narrowed down the problem.
So here are the steps to replicate the situation.
Create a CarouselView.
Create a ObservableCollection<T> in the code behind and assign it to the ItemSource.
Create a method and subscribe it to the CurrentItemChanged event of the CarouselView. This method must at some point remove an element from the ItemSource that has an index between 0 and the index of the CurrentItem.
Now deploy the app and swipe the CarouselView once. This will result in an endless loop of scrolls that will keep going untill all of the items are removed from the ItemSource.
The method from step 3 must look like below.
bool FirstTime = true;
private void StateChanged(object s, EventArgs e)
{
// Pass the first call which is made right after the Carousel is initialized.
if (FirstTime) { FirstTime = false; return; }
var currentItem = (Model)Carousel.CurrentItem; // For debug.
var index = Models.IndexOf(currentItem); // Same.
// Step 3's requirement
Models.RemoveAt(0);
}
When you instead for example add a button to the page and assign the method you've created at the step 3 to it's Clicked event, and continue with the 4th step and manually press button after each scroll the endless loop won't occur.
I don't know if this is a feature or a bug but this certainly was unexpected, at least for me. I would love to figure out how to overcome this problem and learn why it works like this.
Note: I'm aware that removing the current item will cause such problem but the described behaviour occurs either ways. Also CarouselView.CurrentItem is updated before the CurrentItemChanged event is fired.

This will result in an endless loop of scrolls that will keep going untill all of the items are removed from the ItemSource.
This is because ObservableCollection has CollectionChanged event which will be called when the data collection is changed. When you remove the first item, the index is refershed and the event will also be triggered.
For this function, you could detect if the current item is the last one to update the data collection. Check the code:
public partial class Page1 : ContentPage
{
CustomViewModel viewModel = new CustomViewModel();
ObservableCollection<CustomModel> collection;
public Page1()
{
InitializeComponent();
BindingContext = viewModel;
collection = viewmodel.DataCollection;
}
private void CarouselView_CurrentItemChanged(object sender, CurrentItemChangedEventArgs e)
{
var item = e.CurrentItem as CustomModel;
var index = collection.IndexOf(item);
if (collection.Count == (index + 1))
{
collection.RemoveAt(0);
collection.Add(new CustomModel { ... });
}
}
}

Related

Why does my sort behavior fire with only one item in the list, and only the first time the collection is added to?

This question is a result of the fix to this problem. After getting the sort behavior to properly sort the ObservableCollection, I now notice that the first time the collection is added to, the CustomSorter handler fires with only the first item in it, and that same item is passed in as both parameters to the method. That is producing a duplicate item in the list.
Here are the pertinent parts of the view model code:
public ObservableCollection<PermissionItemViewModel> PermissionItems { get; private set; }
private void FetchRoleData()
{
PermissionItems.Clear();
if (SelectedRole != null)
{
using (var context = new myDataContext(new myDbFactory().GetConnectionString()))
{
foreach (PermissionsEnum permission in Enum.GetValues(typeof(PermissionsEnum)))
PermissionItems.Add(new PermissionItemViewModel(permission, SelectedRole[permission]));
}
}
}
All subsequent manipulations of that collection do not do this...it only happens the first time through the FetchRoleData method. Why?
EDIT:
Some additional information. The CustomSort property is set when the CollectionViewSource fires its Filter event (the only event it has AFAIK). I couldn't come up with any better trigger to get it set. The OnAttached override is too soon, as the View member of the CollectionViewSource is not set yet by that point. Catch 22, I guess. That is happening immediately after that first collection item is added. If this is due to the order in which things are being set, then are there any recommendations for a change?
I don't know how or where you're setting up the filter handler. Here's an example of how to set a custom sort on a CollectionViewSource when its View property changes. That's when you want to do it. This assumes that it's in the resources for a Window (or at least someplace where the Window can find it). But once you have cvs, wherever it comes from and however you got your mitts on it, the rest is the same.
public MainWindow()
{
InitializeComponent();
var cvs = FindResource("MyCollectionViewSource1") as CollectionViewSource;
var dpdView = DependencyPropertyDescriptor.FromProperty(
CollectionViewSource.ViewProperty, typeof(CollectionViewSource));
dpdView.AddValueChanged(cvs, (s, e) =>
{
if (cvs.View is ListCollectionView lvc)
{
lvc.CustomSort = new CustomSorter();
}
});
}
I'm baffled by your claim that the first item in the collection is being duplicated. No code you've shown, and no code I've given you, could have that effect. You'll have to share code that demonstrates that issue.

Observable collection removing item only once, when tried again doesnt work - Windows phone 8 - C#

I am writing my first application for WP8 platform in C#. I implemented three datatypes namely locationModel which has locationGroups. Each locationGroup has a ObservableCollection of type locationData.
locationData has two double types for latitude and longitude and a title string.
I used a textblock inside a stackpanel to show the locationData element's title, where the lat long are hidden to user.
There is a context menu on each of this textblock element which enable the user to delete the respective locationData.
When I open the app and delete any item, it succesfully does and updates the view too. But when I do it for another item it just doesnt work. I cannot delete more than one items for each time I open the app.
I used breakpoints to see where the problem is. the selected locationData is succesfully passed to the App.ViewModel.LocationModel.Items.Remove(). But it just that they are not deleted from the observable collection. I even tried to see the index of the locationData in observable collection and use RemoveAt method. Even it doesnt work.
I did a lot of research to find the problem, but no one seems to face the same problem as me. I referred to msdn article on how to implement inotifypropertychanged to update the collection. But its too complex for me to understand that.
I dont really understand why the observable collection delete the item for the second time even though if I pass the index of that item. And my usage of breakpoints showed me that the data is not even null.
So kindly tell me what is causing this problem and how do I overcome it so that I can implement my own workaround and not face this issue again. I can show you the code if you want me to.
Thanks.
CODE:
Adding an item
private void SaveLocationData(LocationData locationData)
{
IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings;
try
{
App.ViewModel.Custom.Items.Add(locationData);
var data = JsonConvert.SerializeObject(App.ViewModel.Custom);
appSettings[LocationModel.CustomKey] = data;
appSettings.Save();
//Notify that data is changed
App.ViewModel.LoadData();
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.RelativeOrAbsolute));
}
catch(IsolatedStorageException ex)
{
MessageBox.Show(ex.Message);
}
}
Deleting item:
private void DeleteLocationData(LocationData locationData)
{
IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings;
try
{
App.ViewModel.Custom.Items.Remove(locationData);
var data = JsonConvert.SerializeObject(App.ViewModel.Custom);
appSettings[LocationModel.CustomKey] = data;
appSettings.Save();
//Notify that data is changed
App.ViewModel.LoadData();
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.RelativeOrAbsolute));
}
catch (IsolatedStorageException ex)
{
MessageBox.Show(ex.Message);
}
}
One more thing that I want to say is, whenever I add a locationData to the collection, it updates automatically. Because adding is done on another page and when the mainpage.xaml loads(in which the observable collection data is), it updates automatically because of the code in OnNavigatedTo method.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
}
}
And LoadData method is :
public void LoadData()
{
Custom = LoadCustomLocations();
IsDataLoaded = true;
}
private LocationGroup LoadCustomLocations()
{
string dataFromAppSettings;
LocationGroup data;
if (IsolatedStorageSettings.ApplicationSettings.TryGetValue(CustomKey, out dataFromAppSettings))
{
data = JsonConvert.DeserializeObject<LocationGroup>(dataFromAppSettings);
}
else
{
data = new LocationGroup();
}
return data;
}
So, can anyone help ?
In the case you described on your comment I think you set the DataContext to your Items. When you create a new Items-List the DataContext will be lost. So you have to reset the DataContext to the new loaded Items-List

How to disable a checkbox in a checkedlistbox?

I have some items in a CheckedListBox, I want to disable the CheckBox of first item in it.
i.e. I want to disable the first item in the CheckedListBox, because I want to tell the user visually that option is not available.
Combining 2 of the above partial answers worked great for me.
Add your items to the list with:
myCheckedListBox.Items.Add(myItem, myState);
Where myState is CheckState.Indeterminate for items that should be disabled.
Then add an event handler to keep those items from being changed:
myCheckedListBox.ItemCheck += (s, e) => { if (e.CurrentValue == CheckState.Indeterminate) e.NewValue = CheckState.Indeterminate; };
This does not allow you to use 'Indeterminate' in this list for its normal purpose but it does give a look very similar to what one would expect for a disabled item and it provides the correct behavior!
Though this post is pretty old, the last added answer has been submitted in April this year,
and I hope this will help someone.
I was after something similar : a checked list box that behaves like
a lot of installers, which offer a list of options where some features are required and
thus are both checked and disabled.
Thanks to this post (Can I use a DrawItem event handler with a CheckedListBox?)
I managed to do that, subclassing a CheckedListBox control.
As the OP in the linked post states, in the CheckedListBox control the OnDrawItem event is never fired,
so subclassing is necessary.
It's very basic, but it works.
This is what it looks like (the CheckBox above is for comparison) :
NOTE: the disabled item is really disabled : clicking on it has no effects whatsoever (as far as I can tell).
And this is the code :
public class CheckedListBoxDisabledItems : CheckedListBox {
private List<string> _checkedAndDisabledItems = new List<string>();
private List<int> _checkedAndDisabledIndexes = new List<int>();
public void CheckAndDisable(string item) {
_checkedAndDisabledItems.Add(item);
this.Refresh();
}
public void CheckAndDisable(int index) {
_checkedAndDisabledIndexes.Add(index);
this.Refresh();
}
protected override void OnDrawItem(DrawItemEventArgs e) {
string s = Items[e.Index].ToString();
if (_checkedAndDisabledItems.Contains(s) || _checkedAndDisabledIndexes.Contains(e.Index)) {
System.Windows.Forms.VisualStyles.CheckBoxState state = System.Windows.Forms.VisualStyles.CheckBoxState.CheckedDisabled;
Size glyphSize = CheckBoxRenderer.GetGlyphSize(e.Graphics, state);
CheckBoxRenderer.DrawCheckBox(
e.Graphics,
new Point(e.Bounds.X + 1, e.Bounds.Y + 1), // add one pixel to align the check gliph properly
new Rectangle(
new Point(e.Bounds.X + glyphSize.Width + 3, e.Bounds.Y), // add three pixels to align text properly
new Size(e.Bounds.Width - glyphSize.Width, e.Bounds.Height)),
s,
this.Font,
TextFormatFlags.Left, // text is centered by default
false,
state);
}
else {
base.OnDrawItem(e);
}
}
public void ClearDisabledItems() {
_checkedAndDisabledIndexes.Clear();
_checkedAndDisabledItems.Clear();
this.Refresh();
}
}
Use it like this:
checkedListBox.Items.Add("Larry");
checkedListBox.Items.Add("Curly");
checkedListBox.Items.Add("Moe");
// these lines are equivalent
checkedListBox.CheckAndDisable("Larry");
checkedListBox.CheckAndDisable(0);
Hope this can help someone.
Disabling items isn't a great idea, the user will have no good feedback that click the check box won't have any effect. You cannot use custom drawing to make it obvious. Best thing to do is to simply omit the item.
You can however easily defeat the user with the ItemCheck event:
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) {
if (e.Index == 0) e.NewValue = e.CurrentValue;
}
To disable any particular item use following:
checkedListBox1.SetItemCheckState(0, CheckState.Indeterminate);
SetItemCheckState takes index of item and CheckState Enum
Indeterminate is used to show shaded appearance
I know it has been a while, but I found this in my search for a list box and thought I would add it to the discussion.
If you have a listbox and want to disable all of the checkboxes so they cannot be clicked, but not disable the control so the user can still scroll etc. you can do this:
listbox.SelectionMode = SelectionMode.None
The CheckedListBox will not work in this way. CheckedListBox.Items is a collection of strings so they cannot be "disabled" as such.
Here are some discussions about possible solutions that might help you: here and here.
This works for me:
checkedListBox1.SelectionMode = SelectionMode.None;
Which means no items can be selected
None: No items can be selected.
For more info, you can check it here: SelectionMode Enumeration.
The solution is to use the event ItemChecking:
_myCheckedListBox.ItemChecking += (s, e) => e.Cancel = true;
This will cancel all the checking on every item, but you can always do more refined solution but testing the current .SelectedItem
Here's how I did it in a helpdesk application I wrote:
First, I made it so the check box was greyed out as I added it to the list during form load:
private void frmMain_Load(object sender, EventArgs e)
{
List<string> grpList = new List<string>();
ADSI objADSI = new ADSI();
grpList = objADSI.fetchGroups();
foreach (string group in grpList)
{
if (group == "SpecificGroupName")
{
chkLst.Items.Add(group, CheckState.Indeterminate);
}
else
{
chkLst.Items.Add(group);
}
}
Then I used an event so that when clicked it ensures it stays clicked:
private void chkLst_SelectedIndexChanged(object sender, EventArgs e)
{
if (chkLst.SelectedItem.ToString() == "SpecificGroupName")
{
chkLst.SetItemCheckState(chkLst.SelectedIndex, CheckState.Indeterminate);
}
}
The idea here is that on my form it's set so that the box checks on item click/select. This way I could kill two birds with one stone. I could keep this event from causing problems when the item is first checked and added during form load. Plus making it check on select allows me to use this event instead of the item checked event. Ultimately the idea is to keep it from messing up during the load.
You'll also notice that it doesn't matter what the index number is, that variable is unknown because in my app it's grabbing a list of groups from AD that exist in a specific OU.
As to whether this is a good idea or not, that's dependent on the situation. I have another app where the item to disable is dependent on another setting. In this app I just want the helpdesk to see that this group is required so they don't go removing them from it.
Try Below Code:
Private Sub CheckedListBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles CheckedListBox1.MouseUp
If (Condition) Then
Me.CheckedListBox1.SelectedIndex = -1
End If
End Sub
I think an alternative solution, is using Telerik components.
A RadListControl can give you that option:

What is the use of ObservableCollection in .net?

What is the use of ObservableCollection in .net?
ObservableCollection is a collection that allows code outside the collection be aware of when changes to the collection (add, move, remove) occur. It is used heavily in WPF and Silverlight but its use is not limited to there. Code can add event handlers to see when the collection has changed and then react through the event handler to do some additional processing. This may be changing a UI or performing some other operation.
The code below doesn't really do anything but demonstrates how you'd attach a handler in a class and then use the event args to react in some way to the changes. WPF already has many operations like refreshing the UI built in so you get them for free when using ObservableCollections
class Handler
{
private ObservableCollection<string> collection;
public Handler()
{
collection = new ObservableCollection<string>();
collection.CollectionChanged += HandleChange;
}
private void HandleChange(object sender, NotifyCollectionChangedEventArgs e)
{
foreach (var x in e.NewItems)
{
// do something
}
foreach (var y in e.OldItems)
{
//do something
}
if (e.Action == NotifyCollectionChangedAction.Move)
{
//do something
}
}
}
An ObservableCollection works essentially like a regular collection except that it implements
the interfaces:
INotifyCollectionChanged,
INotifyPropertyChanged
As such it is very useful when you want to know when the collection has changed. An event is triggered that will tell the user what entries have been added/removed or moved.
More importantly they are very useful when using databinding on a form.
From Pro C# 5.0 and the .NET 4.5 Framework
The ObservableCollection<T> class is very useful in that it has the ability to inform external objects
when its contents have changed in some way (as you might guess, working with
ReadOnlyObservableCollection<T> is very similar, but read-only in nature).
In many ways, working with
the ObservableCollection<T> is identical to working with List<T>, given that both of these classes
implement the same core interfaces. What makes the ObservableCollection<T> class unique is that this
class supports an event named CollectionChanged. This event will fire whenever a new item is inserted, a current item is removed (or relocated), or if the entire collection is modified.
Like any event, CollectionChanged is defined in terms of a delegate, which in this case is
NotifyCollectionChangedEventHandler. This delegate can call any method that takes an object as the first parameter, and a NotifyCollectionChangedEventArgs as the second. Consider the following Main()
method, which populates an observable collection containing Person objects and wires up the
CollectionChanged event:
class Program
{
static void Main(string[] args)
{
// Make a collection to observe and add a few Person objects.
ObservableCollection<Person> people = new ObservableCollection<Person>()
{
new Person{ FirstName = "Peter", LastName = "Murphy", Age = 52 },
new Person{ FirstName = "Kevin", LastName = "Key", Age = 48 },
};
// Wire up the CollectionChanged event.
people.CollectionChanged += people_CollectionChanged;
// Now add a new item.
people.Add(new Person("Fred", "Smith", 32));
// Remove an item.
people.RemoveAt(0);
Console.ReadLine();
}
static void people_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
// What was the action that caused the event?
Console.WriteLine("Action for this event: {0}", e.Action);
// They removed something.
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{
Console.WriteLine("Here are the OLD items:");
foreach (Person p in e.OldItems)
{
Console.WriteLine(p.ToString());
}
Console.WriteLine();
}
// They added something.
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
// Now show the NEW items that were inserted.
Console.WriteLine("Here are the NEW items:");
foreach (Person p in e.NewItems)
{
Console.WriteLine(p.ToString());
}
}
}
}
The incoming NotifyCollectionChangedEventArgs parameter defines two important properties,
OldItems and NewItems, which will give you a list of items that were currently in the collection before the event fired, and the new items that were involved in the change. However, you will want to examine these lists only under the correct circumstances. Recall that the CollectionChanged event can fire when
items are added, removed, relocated, or reset. To discover which of these actions triggered the event,
you can use the Action property of NotifyCollectionChangedEventArgs. The Action property can be
tested against any of the following members of the NotifyCollectionChangedAction enumeration:
public enum NotifyCollectionChangedAction
{
Add = 0,
Remove = 1,
Replace = 2,
Move = 3,
Reset = 4,
}
Explanation without Code
For those wanting an answer without any code behind it (boom-tish) with a story (to help you remember):
Normal Collections - No Notifications
Every now and then I go to NYC and my wife asks me to buy stuff. So I take a shopping list with me. The list has a lot of things on there like:
Louis Vuitton handbag ($5000)
Clive Christian’s Imperial Majesty Perfume ($215,000 )
Gucci Sunglasses ($2000)
hahaha well I"m not buying that stuff. So I cross them off and remove them from the list and I add instead:
12 dozen Titleist golf balls.
12 lb bowling ball.
So I usually come home without the goods and she's never pisssssssed off the thing is that she doesn't know about what i take off the list and what I add onto it; she gets no notifications.
The ObservableCollection - notifications when changes made
Now, whenever I remove something from the list: she get's a notification.
The observable collection works just the same way. If you add or remove something to or from it: someone is notified.
And when they are notified, then bunker down or run for cover! Of course, the consequences are customisable via an event handler.
Silly story, but hopefully you'll remember the concept now.
One of the biggest uses is that you can bind UI components to one, and they'll respond appropriately if the collection's contents change. For example, if you bind a ListView's ItemsSource to one, the ListView's contents will automatically update if you modify the collection.
EDIT:
Here's some sample code from MSDN:
http://msdn.microsoft.com/en-us/library/ms748365.aspx
In C#, hooking the ListBox to the collection could be as easy as
listBox.ItemsSource = NameListData;
though if you haven't hooked the list up as a static resource and defined NameItemTemplate you may want to override PersonName's ToString(). For example:
public override ToString()
{
return string.Format("{0} {1}", this.FirstName, this.LastName);
}
it is a collection which is used to notify mostly UI to change in the collection , it supports automatic notification.
Mainly used in WPF ,
Where say suppose you have UI with a list box and add button and when you click on he button an object of type suppose person will be added to the obseravablecollection and you bind this collection to the ItemSource of Listbox , so as soon as you added a new item in the collection , Listbox will update itself and add one more item in it.
class FooObservableCollection : ObservableCollection<Foo>
{
protected override void InsertItem(int index, Foo item)
{
base.Add(index, Foo);
if (this.CollectionChanged != null)
this.CollectionChanged(this, new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Add, item, index);
}
}
var collection = new FooObservableCollection();
collection.CollectionChanged += CollectionChanged;
collection.Add(new Foo());
void CollectionChanged (object sender, NotifyCollectionChangedEventArgs e)
{
Foo newItem = e.NewItems.OfType<Foo>().First();
}
ObservableCollection Caveat
Mentioned above (Said Roohullah Allem)
What makes the ObservableCollection class unique is that this
class supports an event named CollectionChanged.
Keep this in mind...If you adding a large number of items to an ObservableCollection the UI will also update that many times. This can really gum up or freeze your UI.
A work around would be to create a new list, add all the items then set your property to the new list. This hits the UI once. Again...this is for adding a large number of items.

Tooltips for CheckedListBox items?

Is there a straighforward way to set additional text to appear in a tooltip when a user's mouse is held over an item in a CheckedListBox?
What I would expect to be able to do in code is:
uiChkLstTables.DisplayOnHoverMember = "DisplayOnHoverProperty"; //Property contains extended details
Can anyone point me in the right direction to do this? I've already found a couple of articles that involve detecting which item the mouse is currently over and creating a new tooltip instance, but this sounds a little too contrived to be the best way.
Thanks in advance.
Add a Tooltip object to your form and then add an event handler for the CheckedListBox.MouseHover that calls a method ShowToolTip();
Add MouseMove event of your CheckedListBox which has the following code:
//Make ttIndex a global integer variable to store index of item currently showing tooltip.
//Check if current location is different from item having tooltip, if so call method
if (ttIndex != checkedListBox1.IndexFromPoint(e.Location))
ShowToolTip();
Then create the ShowToolTip method:
private void ShowToolTip()
{
ttIndex = checkedListBox1.IndexFromPoint(checkedListBox1.PointToClient(MousePosition));
if (ttIndex > -1)
{
Point p = PointToClient(MousePosition);
toolTip1.ToolTipTitle = "Tooltip Title";
toolTip1.SetToolTip(checkedListBox1, checkedListBox1.Items[ttIndex].ToString());
}
}
Alternately, you could use a ListView with checkboxes instead. This control has
builtin support for tooltips.
Contrived or not; that's what there is...
I'm not aware of an easier way than you have already described (although I'd probably re-use a tooltip instance, rather than creating new all the time). If you have articles that show this, then use them - or use a 3rd party control that supports this natively (none leap to mind).
I would like to expand upon Fermin's answer in order to perhaps make his wonderful solution slightly more clear.
In the form that you're working in (likely in the .Designer.cs file), you need to add a MouseMove event handler to your CheckedListBox (Fermin originally suggested a MouseHover event handler, but this did not work for me).
this.checkedListBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.showCheckBoxToolTip);
Next, add two class attributes to your form, a ToolTip object and an integer to keep track of the last checkbox whose tool tip was shown
private ToolTip toolTip1;
private int toolTipIndex;
Finally, you need to implement the showCheckBoxToolTip() method. This method is very similar to Fermin's answer, except that I combined the event callback method with the ShowToolTip() method. Also, notice that one of the method parameters is a MouseEventArgs. This is because the MouseMove attribute requires a MouseEventHandler, which then supplies MouseEventArgs.
private void showCheckBoxToolTip(object sender, MouseEventArgs e)
{
if (toolTipIndex != this.checkedListBox.IndexFromPoint(e.Location))
{
toolTipIndex = checkedListBox.IndexFromPoint(checkedListBox.PointToClient(MousePosition));
if (toolTipIndex > -1)
{
toolTip1.SetToolTip(checkedListBox, checkedListBox.Items[toolTipIndex].ToString());
}
}
}
Run through your ListItems in your checkbox list of items and set the appropriate text as the item 'title' attribute, and it will display on hover...
foreach (ListItem item in checkBoxList.Items)
{
//Find your item here...maybe a switch statement or
//a bunch of if()'s
if(item.Value.ToString() == "item 1")
{
item.Attributes["title"] = "This tooltip will display when I hover over item 1 now, thats it!!!";
}
if(item.Value.ToString() == "item 2")
{
item.Attributes["title"] = "This tooltip will display when I hover over item 2 now, thats it!!!";
}
}

Categories