0
votes

I have a listbox defined in a WPF window as follows:

<ListBox ItemsSource="{Binding Values}" SelectedItem="{Binding SelectedValue}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Border BorderThickness="1" BorderBrush="Black" Margin="5">
                <StackPanel Margin="5">
                    <TextBlock FontWeight="Bold" Text="{Binding}"/>
                    <StackPanel Orientation="Horizontal">
                        <Label>Is Selected: </Label>
                        <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsSelected}"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <Label>Selected Item:</Label>
                        <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=ListBox}, Path=SelectedItem}"/>
                    </StackPanel>
                </StackPanel>
            </Border>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

And on the view model:

    private string selectedValue;

    private ObservableCollection<string> values;

    public MainWindowViewModel()
    {
        this.values = new ObservableCollection<string>(new[] { "Fish", "Chips", "Peas" });
    }

    public ObservableCollection<string> Values
    {
        get
        {
            return this.values;
        }
    }

    public string SelectedValue
    {
        get { return this.selectedValue; }
        set
        {
            this.selectedValue = value;

            if (value == "Peas")
            {
                this.SelectedValue = null;
            }

            this.OnPropertyChanged();
        }
    }

Each entry in the listbox displays its text and also a pair of textblocks indicating whether the listboxitem's IsSelected is set, and also what the current SelectedItem of the listbox is.

Everything works fine, until the "Peas" option is selected. The view model has a piece of code which sets the viewmodel's SelectedValue to null in that instance, which in turn sets the listbox's SelectedItem property to null (overriding the fact that the user just clicked "Peas").

However, the ListBoxItem's IsSelected property for "Peas" does not get set to false even though the ListBox now has no selected item.

Any suggestions how to force the ListBoxItem to have IsSelected=false as well?

1
Did you try setting the selectedindex value to a negative value?Shakti Prakash Singh
@ShaktiPrakashSingh what do you mean? I'm not touching the SelectedIndex property at all, just the SelectedItem, via binding to the view model property. That should be enough, right?Stephen Holt
No, that would not help you achieve what you are trying to do. Setting SelectedValue to null does not mean there is no value selected, it means that the current selected value is 'null' and hence SelectedItem is null too. You would need to reset the ComboBox selection somehow.Shakti Prakash Singh
May be you can try and reset the source collection, this is just a workaround though. Set the values = null and then again again restore the collection, values.Shakti Prakash Singh
@ShaktiPrakashSingh but setting SelectedValue to null really should cause the listbox to have no value selected. If I put a button outside the listbox, which calls the same code, SelectedValue = null; then it works fine. The problem is with the fact that the user explicitly selected that ListBoxItem, but the code then tries to immediately deselect it... I suspect it's related to a conflict in the TwoWay binding.Stephen Holt

1 Answers

0
votes

OK, I have found a workaround which seems to do the job. I have replaced the block

if (value == "Peas")
{
    this.SelectedValue = null;
}

with

if (value == "Peas")
{
    Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => this.SelectedValue = null));
}

essentially deferring the setting of the SelectedValue to null until after the block of code handling the user click has completed, and thus ensuring they don't interfere with each other.

I'll mark this as the accepted answer if nobody else has a more "elegant" solution to this!