0
votes

In a WPF ComboBox how can you make a null instance in ItemsSource selectable when using DisplayMemberPath?

I am binding to a collection of objects and have added null to that collection. I have also bound SelectedItem to property. When selecting values that are not null, my SelectedItem property changes correctly. But when I select the null item from the drop down list, my SelectedItem property does not change.

I've isolated it to the use of DisplayMemberPath, i.e. it wouldn't happen with a collection of strings because you wouldn't use DisplayMemberPath.

This all sort of makes sense to me as there is no instance of my objects where DisplayMemberPath is blank or null, there's only a null item in the List. However, I'm trying to find the best way to provide a way blank out the ComboBox.

I guess I could create an instance of my object where the value of the DisplayMemberPath property is a blank string, but that seems a little hacky to me.

Any suggestions?

My example follows:

Here's the class I'm filling my ItemsSource up with:

public class Car
{
    public string Make { get; set; }

    public Car(string make)
    {
        Make = make;
    }

}

Here's my xaml:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <ComboBox SelectedItem="{Binding MyCar}" ItemsSource="{Binding MyCars}" DisplayMemberPath="Make" />
</Grid>

And here's my code behind:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private Car myCar = null;

    public List<Car> MyCars { get; set; }

    public Car MyCar
    {
        get { return myCar; }
        set
        {
            if (myCar != value)
            {
                myCar = value;
                OnPropertyChanged("MyCar");
            }
        }
    }


    public MainWindow()
    {
        MyCar = null;

        MyCars = new List<Car>();
        MyCars.Add(null);
        MyCars.Add(new Car("Ford"));
        MyCars.Add(new Car("Chevy"));
        MyCars.Add(new Car("Toyota"));

        InitializeComponent();

    }


    #region INotifyPropertyChanged
    /// <summary>
    /// Occurs when a property value changes.
    /// </summary>
    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// This function is used to raise an PropertyChanged event.
    /// </summary>
    /// <param name="prop">The name of the property whose value changed.</param>
    internal void OnPropertyChanged(string prop)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(prop));
        }
    }
    #endregion

}
2
Would MyCars.Add(new Car("")); fit your requirements, I'm guessing you're hitting issue trying to bind to the Make property of nullKevin DiTraglia
And you think entering a value of null is not hacky? Null does not have a property Make.paparazzo
@KevinDiTraglia it's not a requirements issue, I can make it work as you describe and adjust my logic as needed, just trying to determine if WPF supported something I wasn't aware ofFodderZone
Use my Selectable<T> approach and you can have an instance of Selectable<Car> with no car.Federico Berasategui

2 Answers

0
votes

Add (in VB so you'll need to convert) a

Public Overrides Function ToString() As String
    If string.isnullorwhitespace(Make) then
        return "no Car"
    else
        return make
    end if
End Function

to your car class then there is no need for displaymemberpath to be used and see if this acts like an itemssource of strings

0
votes
 private string[] Logo_menu_array = { "Assets/star-6-48.ico", "/Assets/note-48.ico", "/Assets/medal-48.ico", "/Assets/joystick-48.ico" };
    private string[] Text_menu_array={"Phổ biến trên YouTuBe","Âm nhạc","Thể thao","Trò chơi"};






    public class listboxitem
    {
        public string textmenu { get; set; }
        public string logomenu { get; set; }
    }



public List<listboxitem> Load_Menu()
    {
        List<listboxitem> text = new List<listboxitem>();
        for (int i = 0; i < Math.Min(Logo_menu_array.Length, Text_menu_array.Length); i++)
        {
            var l = new listboxitem();
            l.logomenu = Logo_menu_array[i];
            l.textmenu = Text_menu_array[i];
            text.Add(l);
        }

        return text;
    }

public MainPage()
    {
        this.InitializeComponent();
        //get menu
         List<listboxitem> menu_list = Load_Menu();
         lst_menu.ItemsSource = menu_list;


    }