How to get selected text from a ComboBox that contains image and text, in WPF (by C#)

رضا جافری 1,296 Reputation points
2022-01-02T10:18:59.517+00:00

First and foremost, I apologize for my grammatical errors; my first language is Persian (Iran).
I want to get selected text from a ComboBox that contains image and text:

161649-printer.jpg

I tried following codes:
WPF (XAML):

        <ComboBox x:Name="PrinterSelection_ComboBox" SelectionChanged="PrinterSelection_ComboBox_SelectionChanged" HorizontalAlignment="Left" Height="51" BorderBrush="DarkGray" VerticalAlignment="Top" Width="334" Margin="14,168,0,0">  
            <ComboBox.ItemTemplate>  
                <DataTemplate>  
                    <WrapPanel Margin="0,5,0,5" Height="45">  
                        <Image x:Name="PrinterImage" Width="65" Height="35" Stretch="Fill" Source="{Binding ComboBoxItemImage}" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="7,0,0,0"/>  
                        <Label x:Name="PrinterName" Content="{Binding ComboBoxItemName}" TextBlock.TextAlignment="Center" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="0,0,0,0"/>  
                    </WrapPanel>  
                </DataTemplate>  
            </ComboBox.ItemTemplate>  
        </ComboBox>  

C#:

    string PrinterName;  
    private void PrinterSelection_ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)  
    {  
        switch(PrinterSelection_ComboBox.SelectedItem!=null)  
        {  
            case true:  
                PrinterName = ((ComboBoxItem)PrinterSelection_ComboBox.SelectedItem).Content.ToString();  
                break;  
        }  
    }  

But in line 6 (C# codes) it shows me this error: 'Unable to cast object of type 'CustomComboBoxItem' to type 'System.Windows.Controls.ComboBoxItem

Who can help me?

Thanks

Developer technologies Windows Presentation Foundation
Developer technologies XAML
Developer technologies C#
0 comments No comments
{count} votes

Accepted answer
  1. Hui Liu-MSFT 48,676 Reputation points Microsoft External Staff
    2022-01-04T02:57:49.757+00:00

    The following code example is done by referring to the solution of vb2ae, you could refer to it to complete your project. If there is any problem, please let me know.
    MainWindow.xaml:

    <StackPanel>  
            <TextBlock x:Name="tb"  Width="200" Height="50" Background="AliceBlue"/>  
            <ComboBox  x:Name="PrinterSelection_ComboBox"   
                       Height="80" SelectedIndex="0" Margin="5 3 5 3" Width="200"   
                       SelectionChanged="PrinterSelection_ComboBox_SelectionChanged"  
                       ItemsSource="{Binding PrinterList}">  
                <ComboBox.ItemTemplate>  
                    <DataTemplate>  
                        <WrapPanel Margin="0,5,0,5" Height="45">  
                            <Image x:Name="PrinterImage" Source="{Binding ComboBoxItemImage}"  
                                   Height="20" Stretch="Fill"  
                                    HorizontalAlignment="Left" VerticalAlignment="Center"/>  
                            <Label x:Name="PrinterName"  Content="{Binding ComboBoxItemName}"  
                                  TextBlock.TextAlignment="Center"   
                                   VerticalAlignment="Center"/>  
                        </WrapPanel>  
                    </DataTemplate>  
                </ComboBox.ItemTemplate>  
            </ComboBox>  
        </StackPanel>  
    

    MainWindow.xaml.cs:

    public partial class MainWindow : Window  
      {  
        public List<MyPrinter> PrinterList { get;private set;}  
        public MainWindow()  
        {  
          InitializeComponent();  
          PrinterList = new List<MyPrinter>();  
          PrinterList.Add(new MyPrinter("Software602 Print2PDF", "Resources/8.jpg"));  
          PrinterList.Add(new MyPrinter("Microsoft XPS Document Writer", "Resources/e1.jpg"));  
          PrinterList.Add(new MyPrinter("Microsoft Print to PDF", "Resources/hd.jpg"));  
          DataContext=this;  
      
        }  
        string PrinterName;  
        private void PrinterSelection_ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)  
        {  
          var selectedItem = PrinterSelection_ComboBox.SelectedItem as MyPrinter;  
          switch (selectedItem != null)  
          {  
            case true:  
              PrinterName = selectedItem.ComboBoxItemName;  
              tb.Text=PrinterName;  
              break;  
          }  
        }  
      }  
      public class MyPrinter : INotifyPropertyChanged  
      {  
        private string name;  
        private string path;  
          
        public string ComboBoxItemName  
        {  
          get { return name; }  
          set  
          {  
            if (name == value) return;  
            name = value;  
            OnPropertyChanged("ComboBoxItemName");  
          }  
        }  
        public string ComboBoxItemImage  
        {  
          get { return path; }  
          set  
          {  
            if (path == value) return;  
            path = value;  
            OnPropertyChanged("ComboBoxItemImage");  
          }  
        }  
        public MyPrinter(string name, string path)  
        {  
          this.ComboBoxItemName = name;  
          this.ComboBoxItemImage = path;  
        }  
        public event PropertyChangedEventHandler PropertyChanged;  
        protected void OnPropertyChanged(string name)  
        {  
          PropertyChangedEventHandler handler = PropertyChanged;  
          if (handler != null)  
          {  
            handler(this, new PropertyChangedEventArgs(name));  
          }  
        }  
      }  
    

    The result:

    162072-5.gif

    Method2:
    View:

    <ComboBox  x:Name="PrinterSelection_ComboBox"   
                       Height="80" SelectedIndex="0" Margin="3" Width="200"   
                       SelectedItem="{Binding Item}"   
                       ItemsSource="{Binding PrinterList}">  
      
    ... code...  
    </ComboBox>  
    

    Whenever the selected item in the ComboBox is changed, so is the Item property. If you want to do something when the selected item is changed, you can do that in the property setter.
    Code in MainWindow class:

    string PrinterName;  
        private MyPrinter item;  
        public MyPrinter Item  
        {  
          get { return item; }  
          set  
          {  
            if (item != value)  
            {  
              item = value;  
              OnPropertyChanged("Item");  
              PrinterName=item.ComboBoxItemName;  
              tb.Text = PrinterName;  
            }  
          }  
        }  
    

    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Ken Tucker 5,861 Reputation points
    2022-01-02T11:27:32.13+00:00

    Looking at your xaml I see you are bound to a custom class because ComboBoxItemImage and ComboBoxItemName are not part of the combobox item.

                 <DataTemplate>
                     <WrapPanel Margin="0,5,0,5" Height="45">
                         <Image x:Name="PrinterImage" Width="65" Height="35" Stretch="Fill" Source="{Binding ComboBoxItemImage}" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="7,0,0,0"/>
                         <Label x:Name="PrinterName" Content="{Binding ComboBoxItemName}" TextBlock.TextAlignment="Center" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="0,0,0,0"/>
                     </WrapPanel>
                 </DataTemplate>
             </ComboBox.ItemTemplate>
    

    I would change my code to this. I am assuming the class name is MyClass you will have to change it to actual class name

     private void PrinterSelection_ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
     {
          var selectedItem = PrinterSelection_ComboBox.SelectedItem as MyClass;
         if(selectedItem!=null)
         {
                 PrinterName = selectedItem.ComboBoxItemName;
         }
     }
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.