Search code examples
c#wpfxamllistboxtextblock

Obtain value from ListBox containing TextBlocks using SelectedItem in WPF


I have a listbox whose data comes from the results of a linq query. The listbox displays everything properly but I cannot figure out how to extract the selected item from the listbox. I have tried a few things and I either get exceptions saying it cannot cast an anonymous type or the values do not hold their values to the next line.

Datasource

    private void FavoritesPopulate()
    {
        dynamic qryFavorties = (from db in AppGlobal.GlobalDataset.Tables[ListFavorites.ListStringName].AsEnumerable()
                                select new { Name = db.Field<string>("SystemName") }).OrderBy(db => db.Name);
        this.lbSystems.DataContext = qryFavorties;
    }

Listbox

<ListBox x:Name="lbSystems" VerticalAlignment="Stretch" DockPanel.Dock="Left" Width="Auto" IsTextSearchEnabled="True" TextSearch.TextPath="Name"
                     Background="Transparent" Foreground="{DynamicResource DynamicFrmFG}" FontFamily="Consolas" 
                     ItemsSource="{Binding}" ItemTemplate="{StaticResource mySystemTemplate}" SelectionChanged="lbSystems_SelectionChanged" >
                <ListBox.Resources>
                    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="{DynamicResource DynamicCtrlHighlight}"/>
                    <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="{DynamicResource DynamicCtrlHighlight}"/>
                </ListBox.Resources>
            </ListBox>

Resource

    <Window.Resources>
    <BooleanToVisibilityConverter x:Key="BoolToVis" />

    <DataTemplate x:Key="mySystemTemplate">
        <StackPanel>
            <TextBlock Text="{Binding Path=Name}" Foreground="{DynamicResource DynamicFrmFG}" FontSize="14" FontFamily="Consolas" />
        </StackPanel>
    </DataTemplate>
    </Window.Resources>

Code I have tried to get the selected system name

ListBoxItem myListBoxItem = (ListBoxItem)(this.lbSystems.ItemContainerGenerator.ContainerFromItem(this.lbSystems.Items.CurrentItem));
            TextBlock tb = (TextBlock)this.lbSystems.SelectedItem;
            ListBoxItem lbi = (this.lbSystems.SelectedItem as ListBoxItem);
            ListItemCollection lbi = this.lbSystems.SelectedItem as ListItemCollection;


            var test = lbi.Content.ToString();

Majority of everything I try when I look at the IDE, in the Watch screen has the variables saying they do not exist in the current context. Then the cast of the TextBlock throws the error:

Unable to cast object of type '<>f__AnonymousType0`1[System.String]' to type 'System.Windows.COntrols.TextBlock'

Can anyone show me what I am doing wrong in trying to retrieve the selected item or if i binded the data wrong and that's why I cannot get the selected item.

Edit: After applying the solution I did have to make another edit to my listbox to make it searchable again.

Previous Code

IsTextSearchEnabled="True" TextSearch.TextPath="Name"

Code to fix it

IsTextSearchEnabled="True" TextSearch.TextPath="{Binding Name}"

Solution

  • You've needlessly created an anonymous type with the line select new { Name = db.Field<string>("SystemName") }. Just select a plain old string using select db.Field<string> instead:

    IEnumerable<string> qryFavorties = (from db in AppGlobal.GlobalDataset.Tables[ListFavorites.ListStringName].AsEnumerable()
        select db.Field<string>("SystemName")).OrderBy(name => name);
    this.lbSystems.DataContext = qryFavorties;
    

    And then of course bind to the (string) item itself:

    <TextBlock Text="{Binding}" ... />
    

    Now the ListBox.SelectedItem should be a string, which you can get in one line by unboxing:

    string selectedValue = (string)this.lbSystems.SelectedItem;