# .NET and More > WPF, WCF, WF >  WPF VB - .NET 3.5/4 : Anyway to "disable" a value in a listbox?

## evanrich

I'm looking for a way, if possible, to make values in a listbox "disabled"  meaning they get greyed out, but not the entire list.   I've got a listbox, that depending on its selected item, populates values into another listbox.   What I'd like to do is have something similar to the following code so that if there are no values to populate into the second listbox, then the line is greyed out.




```
SQL.CommandText = "SELECT COUNT * FROM Topics WHERE Question =" & ProductID
SQLResult = SQL.ExecuteNonQuery()
Count = SQLResult

If Count =0 Then

lstProducts.selectedRow(2).enabled = false

End IF
```

obviously the last line (lstproducts.selectedrow.enabled) is a bogus line, but I'm looking for something like that, even if it's applying a template to the box or something.

----------


## chris128

There are probably several ways to do it - personally I would use a Converter (might not be suitable for you but without knowing more about what you are doing its hard to say). It might be a bit hard to explain this but I've done it successfully in the past with relative ease. 
Basically what you would do is have a property on your listbox items (assuming you are adding instances of your own class to the listbox rather than just strings) that specifies whether or not this item should be greyed out and you would pass this value in via data binding to the Foreground property of whatever it is that you want to be greyed out (a TextBlock or whatever it is that is displaying the item) and tell it to use a converter. The converter then takes the value of the property, which in this case would just need to be a boolean, and if it is True it returns a black Brush object (which is what will get assigned to the Foreground property of our TextBlock) and if it is False then it returns a grey Brush  :Smilie:  The great thing about this is that you don't have to just limit it to greying out the text like you would in Winforms, you can use this method to affect any properties you like and depending on how elaborate your DataTemplate is for these items there could be a much 'cooler' way of showing that the item is disabled  :Smilie: 
I'll put together a basic example anyway as that probably wasn't the best explanation in the world...

Oh and if you don't want to have to determine if the item needs to be disabled before it is added to the listbox then you could probably just implement INotifyPropertyChanged on that property I talked about creating and then when the user selects an item you execute your SQL statement and assign the relevant value to the property for the selected item. Personally I would think it is better to grey out the items before the user clicks on them though.

----------


## chris128

OK I've put together a very simple example that just uses a property named Disabled on each item to determine what colour the text should be. Like I said you could do much more with this but its just an example  :Smilie: 

First of all here's a screenshot:



and here is the full XAML for that window (I'll post the VB code behind in the next post) :



```
<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:ExampleConverter x:Key="ExampleConverterResource" />
        <DataTemplate x:Key="ExampleDataTemplate">
            <Grid>
                <TextBlock Text="{Binding Path=ExampleTitle}" Foreground="{Binding Path=Disabled,Converter={StaticResource ExampleConverterResource}}" />
            </Grid>
        </DataTemplate>
    </Window.Resources>
    <Grid>
         <ListBox Name="ExampleListBox" Margin="10" ItemTemplate="{StaticResource ExampleDataTemplate}" />
    </Grid>
</Window>
```

----------


## chris128

and here's all of the VB code

First of all this is the ExampleConverter class that we call from the XAML to actually convert the Disabled property value into a colour so that we can assign it to the Foreground property of the Textblock in the data template:

vb Code:
<ValueConversion(GetType(Boolean), GetType(Brush))> _ '<-- This tells the converter what type of value to expect for the input and output of this conversion
Public Class ExampleConverter : Implements IValueConverter
     Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
        'This method gets called when the DataTemplate populates the TextBlock's Foreground property and the "value" object passed
        'in is the value of our Disabled property for this item as that is what we specified for the Foreground property data binding in the XAML
        Dim BooleanValue As Boolean = CBool(value)
        If BooleanValue = True Then
            Return Brushes.Gray 'Return a grey coloured brush if the Disabled property was set to True
        Else
            Return Brushes.Black 'Else return a black coloured brush
        End If
    End Function
     Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Return Nothing 'Don't care as we won't be converting it back
    End Function
 End Class

Now here's the code in the window itself:

vb Code:
Class MainWindow 
     Private ObjectList As New List(Of ExampleItemClass) 'This is the list that the listbox will be bound to
     Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
        'Add items to a list and set the Disabled property on some of them
        ObjectList.Add(New ExampleItemClass With {.ExampleTitle = "Example enabled item"})
        ObjectList.Add(New ExampleItemClass With {.ExampleTitle = "Example disabled item", .Disabled = True})
        ObjectList.Add(New ExampleItemClass With {.ExampleTitle = "Another example enabled item"})
        ObjectList.Add(New ExampleItemClass With {.ExampleTitle = "and another example enabled item"})
        ObjectList.Add(New ExampleItemClass With {.ExampleTitle = "Another example disabled item", .Disabled = True})
         'Set the listbox item source to our list of items
        ExampleListBox.ItemsSource = ObjectList
    End Sub
 End Class

and our basic item class that we add instances of to the listbox, that has the Disabled property we use in the converter:

vb Code:
Public Class ExampleItemClass
     Private _ExampleTitle As String = String.Empty
    Public Property ExampleTitle() As String
        Get
            Return _ExampleTitle
        End Get
        Set(ByVal value As String)
            _ExampleTitle = value
        End Set
    End Property
     Private _Disabled As Boolean = False
    Public Property Disabled() As Boolean
        Get
            Return _Disabled
        End Get
        Set(ByVal value As Boolean)
            _Disabled = value
        End Set
    End Property
 End Class

Hope that helps and let me know if you have any questions  :Smilie:  Oh and I know you might be thinking what the hell, all that just to grey out an item in a listbox... but remember that this can do much more than that and this is just a basic example. There may well be a better and simpler way to simply grey out the text as you wanted but I can't think of anything off the top of my head and this is a very useful 'trick' to learn  :Smilie: 
Just as a quick example of the kind of other things you can do with this technique, here's a screenshot of a chat application I made ages ago - the colour of each user and also the image for each user is selected automatically via a converter based on their current status (away, busy etc) :

----------


## Evil_Giraffe

The problem with the ValueConverter approach is that you're baking the UI look into the ValueConverter.  This is far from ideal.  Using a trigger as part of the DataTemplate when templating the ExampleItemClass removes the need for the converter and puts all the code relating to the look of the item in one place.  Any further changes required for a "disabled" item are then simply additional Setter elements inside the DataTrigger, and not additional ValueConverter classes:



```
<Window x:Class="WpfTestBed.Window3"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:WpfTestBed="clr-namespace:WpfTestBed"
        Title="Window3" Height="300" Width="300">
    <Window.Resources>
        <DataTemplate DataType="{x:Type WpfTestBed:ExampleItemClass}">
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Disabled}" Value="True">
                    <Setter Property="Control.Foreground" Value="Gray" />
                </DataTrigger>
            </DataTemplate.Triggers>
            <TextBlock Text="{Binding ExampleTitle}" />
        </DataTemplate>
    </Window.Resources>
    
    <Grid>
        <ListBox>
            <ListBox.Items>
                <WpfTestBed:ExampleItemClass ExampleTitle="Not Disabled" Disabled="False" />
                <WpfTestBed:ExampleItemClass ExampleTitle="Disabled" Disabled="True" />
            </ListBox.Items>
        </ListBox>
    </Grid>
</Window>
```

----------


## minter

Hey Chris128, Can you post the source code for the "ProtoChat" status

----------

