简体   繁体   中英

Displaying a selected ComboBox Item in WPF

I'm trying to construct a ComboBox that will display a selected item. I can get the combo box to display the options easily enough, but getting the selected item to display is not working. The selected item refers to a value being pulled from a database.

I know that the set method is working because I can successfully store the user's choice. However, I cannot seem to get the ComboBox to populate the selected item when I grab it from the database.

I've been frustrated over this for a few weeks now, and I feel like the mistake is simple.

Scenario:

I have an Animal Model

public class AnimalModel
{
    public string AnimalName { get; set; }
    ...
}

I have an AnimalViewModel for each Animal :

public class AnimalViewModel: BindableBase
{
    private AnimalViewModel _animal;

    public AnimalViewModel(AnimalModel animal)
    {
        _animal = animal;
    }

    public string AnimalName
    {
        get { return _animal.Name; }
        set
        {
            if (value != this._animal.Name)
            {
                this._animal.Name = value;
                OnPropertyChanged("AnimalName");
            }
        }
    }
    ...
}

I have an ObservableCollection of AnimalViewModel objects:

public class TemplateViewModel : BindableBase
{
    private ObservableCollection<AnimalViewModel> _animals;
    public TemplateViewModel(...)
    {
        _animal = methodReturnsAnObservableCollectionOfAnimalViewModels();
    }

    public ObservableCollection<AnimalViewModel> Animals
    {
        get { return _animals; }
        set
        {
            if (value != this._animals)
            {
                this._animals = value;
                OnPropertyChanged("Animals");
            }
        }
    }
}

With this in place, I can easily display a list of AnimalName s in the ComboBox:

<ComboBox ItemsSource="{Binding Animals}" 
          DisplayMemberPath="AnimalName" 
          IsEditable="True" 
          IsReadOnly="True" 
          Text="--- Select Animal ---"/>

I now bind to a SelectedItem

public class TemplateViewModel
{
    ...
    private AnimalViewModel _selectedAnimal;
    public TemplateViewModel(MyObject, ...)
    {
        ...
        _selectedAnimal = new AnimalViewModel(new AnimalModel() { AnimalName = MyObject.AnimalName });
    }
    ...
    public AnimalViewModel SelectedAnimal
    {
        get { return _selectedAnimal; }
        set
        {
            if (value != _selectedAnimal)
            {
                _selectedAnimal = value;
                AnimalName = value.AnimalName;
                OnPropertyChanged("SelectedAnimal");
            }
        }
    }
}

So now, I have:

<ComboBox ItemsSource="{Binding Animals}" 
          DisplayMemberPath="AnimalName" 
          SelectedItem={Binding SelectedAnimal} 
          SelectedValuePath="AnimalName" 
          IsEditable="True" IsReadOnly="True" 
          Text="--- Select Animal ---"/>

Unfortunately, this does not populate the ComboBox with an Animal. It just pulls up the default choice Select Animal with the options populated. It does set the item correctly.

Any help would be appreciated.

You need to access the actual reference to the animal in question.

In the codebehind you create an animal which looks like the animal in the ObservableCollection, but its not the animal by reference .

Change ( after Animals is loaded )

 _selectedAnimal = new AnimalViewModel(...);

to ( only use the Property accessor, not the backing store variable; so the change event fires, btw )

SelectedAnimal = Animals[0];

Test app (formatting like grid row/column removed)

<Label>SelectedItem</Label>
<TextBlock  Text="{Binding SelectedItem, ElementName=cbMain}"/>
<Label >SelectedValue</Label>
<TextBlock Text="{Binding SelectedValue, ElementName=cbMain}"/>
<Button  Click="ChangeSelectedValue">Set Selected Value</Button>
<ComboBox Name="cbMain"
            ItemsSource="{Binding Ships}"
            SelectedItem="{Binding Ships[0]}"
            SelectedValuePath="Name"
            Text="Select a Ship"/>

Result on Load of screen:

在此处输入图片说明

I think this is a naming discrepancy between SelectedValuePath="AnimalName" and your property.

public string Animal //<----Should Be AnimalName!
{
    get { return _animal.Name; }
    set
    {
        if (value != this._animal.Name)
        {
            this._animal.Name = value;
            OnPropertyChanged("AnimalName");
        }
    }
}

change your property to AnimalName and you're good to go.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM