Reputation: 30488
We're trying to create a ListBox which has a few items inside that the user cannot select. Think the group headings in a grouped listbox, except these are independent items (i.e. no indented children.) We just want to display a message in the list.
Here's a mock-up of what we currently display if there are 'Foo' items...
Foo 1
Foo 2
Foo 3
-------------- <-- This is of type 'Separator' so it's styled as not-selectable by default.
Add new Foo...
Manage Foos...
...and if there aren't any Foo items, we display this...
[No Foo Items] <-- This one should not be selectable, the same as a separator
-------------- <-- This is of type 'Separator' so it's styled as not-selectable by default.
Add new Foo...
Manage Foos...
Now again, we already have the code that properly handles what's displayed (see below). We're wondering what's the proper way to disable that entry from being able to be selected.
What we don't know is how to style that ListBoxItem so the selection skips right over it, nor can the user click on it.
Someone asked me to see my code, so here it is. Not really relevant to the question, but should show people how I did this.
Note: We template the string.Empty
in the XAML to show the localized 'No xxx Items' message. string.Empty
is just a placeholder that we can target.
Note 2: FauxData is a simple library of items and collections used for testing so I don't have to constantly create them from scratch. SimpleItemCollection for instance creates ten SimpleItem objects in the constructor, pre-populated with things like Name, Description, IsSelected, etc. all fully supporting INotifyPropertyChanged and collection change notifications. I have the same thing with HierarchicalItemsCollection which adds Parent, Children and IsExpanded, etc. It saves a LOT of work when testing code and controls!
Finally, this is from a simple test, or 'playground' app. As such, it's not supposed to represent the best way to do things, just to show a concept. Yes, it can be cleaned up a lot, but you get the general idea.
Anyway, on to the code...
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using FauxData;
namespace Playground.ListTest
{
[LaunchEntry("List Test")]
public partial class Main : Window
{
SimpleItemCollection itemsCollection = new SimpleItemCollection(); // Default constructor creates 10 items
public Main()
{
InitializeComponent();
MainListBox.ItemsSource = CreateCompositeCollection();
}
private CompositeCollection CreateCompositeCollection()
{
var EmptyHolder = new ObservableCollection<object>();
itemsCollection.CollectionChanged += (s,e) => {
if(itemsCollection.Count != 0)
EmptyHolder.Clear();
else if(EmptyHolder.Count == 0)
EmptyHolder.Add(string.Empty);
};
var cc = new CompositeCollection();
cc.Add(new CollectionContainer(){ Collection = itemsCollection });
cc.Add(new CollectionContainer(){ Collection = EmptyHolder });
cc.Add(new Separator());
cc.Add(ApplicationCommands.New); // <-- Pops a dialog to enter a new item
cc.Add(ApplicationCommands.Open); // <-- Shows an item management window
return cc;
}
private void Test_Click(object sender, RoutedEventArgs e)
{
if(itemsCollection.Count != 0)
itemsCollection.Clear();
else
itemsCollection.Add(new SimpleItem(){Name = "New item" });
}
}
}
Upvotes: 2
Views: 5718
Reputation: 45106
If you don't want it to gray out then IsHitTestVisible seems to achieve that.
<ListBox SelectionMode="Multiple">
<ListBoxItem IsEnabled="False">HEsder</ListBoxItem>
<ListBoxItem IsEnabled="True">1</ListBoxItem>
<ListBoxItem IsHitTestVisible="False">-----</ListBoxItem>
<ListBoxItem IsEnabled="True">2</ListBoxItem>
</ListBox>
If you are Binding the you would need to user a trigger.
Upvotes: 1
Reputation: 185553
As Focusable="false"
does not cover all options (e.g. click and drag select) i would recommend setting IsEnabled
to false
instead.
(The greyed out text is a matter of the ListBoxItem
style/template, so if you do not like it you will need to override it)
Upvotes: 3
Reputation: 30488
Wow! That was easy! On the ListBoxItem
you want to skip, you just set Focusable
to False
.
Done and done!
Upvotes: 1