简体   繁体   中英

Can't change ComboBox selection when bound to ObservableCollection (WPF)

I'm trying to create an edit form for editing properties of a custom set of TV Series objects. One of the properties holds a collection of all owned media formats (DVD, Blu-ray, etc) for that particular series that will be displayed in a ComboBox . Items are added to the ComboBox via a separate popup window and items are to be removed from the ComboBox by selecting the item and clicking a remove Button .

I can add new entries to the MediaOwned ComboBox just fine, but when I try to select a specific ComboBox item to test the remove Button I find that I can only ever select the first entry. Can someone please tell me if I've missed something embarrassingly obvious, thanks.

Here is the problematic property:

    private ObservableCollection<string> _mediaOwned = new ObservableCollection<string>();
    public ObservableCollection<string> MediaOwned
    {
        get { return _mediaOwned; }
        set
        {
            _mediaOwned = value;
            OnPropertyChanged(new PropertyChangedEventArgs("MediaOwned"));
        }
    }

Here are the other relevant code behind:

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        // Create binding for the ListBox.
        Binding listBinding = new Binding();
        listBinding.Source = show.Series;
        listBinding.Mode = BindingMode.OneWay;
        listBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        lbSeries.SetBinding(ListBox.ItemsSourceProperty, listBinding);

        // Create binding for the ComboBox.
        Binding myBinding = new Binding();
        myBinding.Path = new PropertyPath("MediaOwned");
        myBinding.Mode = BindingMode.TwoWay;
        myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        cbMediaOwned.SetBinding(ComboBox.ItemsSourceProperty, myBinding);
    }

    private void btnRemoveMedia_Click(object sender, RoutedEventArgs e)
    {
        Series series = (Series)lbSeries.SelectedItem;
        series.MediaOwned.Remove(cbMediaOwned.Text);
    }

And here is the XAML code:

        <Border Style="{StaticResource PanelBorderStyle}" DockPanel.Dock="Left" Margin="0,8,8,0" 
                DataContext="{Binding ElementName=lbLists, Path=SelectedItem}">
            <DockPanel VerticalAlignment="Top">
                <StackPanel>
                    <ListBox x:Name="lbSeries" Style="{StaticResource BasicListStyle}" Width="180" Height="300" 
                             DisplayMemberPath="Title" SelectionMode="Single" LayoutUpdated="lbSeries_LayoutUpdated">
                    </ListBox>
                </StackPanel>
                
                <StackPanel x:Name="editPanel" DataContext="{Binding ElementName=lbSeries, Path=SelectedItem}">
                    <StackPanel  Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 4, 0, 0">
                        <TextBlock Style="{StaticResource SmallFont}" Width="100">Title</TextBlock>
                        <TextBox x:Name="txtTitle" Style="{StaticResource TextBoxStyle}" Text="{Binding Path=Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="200" Margin="8, 8, 16, 8"></TextBox>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top">
                        <TextBlock Style="{StaticResource SmallFont}" Width="100">Media owned</TextBlock>

                        <ComboBox x:Name="cbMediaOwned" Style="{StaticResource ComboBoxStyle}"  Width="150" Margin="8,8,6,8" 
                                ></ComboBox>

                        <Button x:Name="btnAddMedia" Style="{StaticResource ToolbarButtonStyle}" Click="btnAddMedia_Click" Margin="0">
                            <StackPanel ToolTip="Add media">
                                <Image Source="Images/add.png" />
                            </StackPanel>
                        </Button>
                        <Button x:Name="btnRemoveMedia" Style="{StaticResource ToolbarButtonStyle}" Click="btnRemoveMedia_Click" Margin="4">
                            <StackPanel ToolTip="Remove media">
                                <Image Source="Images/remove.png" />
                            </StackPanel>
                        </Button>
                    </StackPanel>
                </StackPanel>
            </DockPanel>
        </Border>

Alternatively I can also remove the binding code in the code behind and replace the ComboBox with the below code (but I still get the same problem - I can't select anything in the ComboBox ):

                    <ComboBox x:Name="cbMediaOwned" Style="{StaticResource ComboBoxStyle}"  Width="150" Margin="8,8,6,8" ItemsSource="{Binding ElementName=lbSeries, Path=SelectedItem.MediaOwned, UpdateSourceTrigger=PropertyChanged}" 
                              SelectedItem="{Binding SelectedMedia, UpdateSourceTrigger=PropertyChanged}"></ComboBox>

SelectedMedia property:

    private string _selectedMedia = "";
    public string SelectedMedia
    {
        get { return _selectedMedia; }
        set
        {
            _selectedMedia = value;
            OnPropertyChanged(new PropertyChangedEventArgs("SelectedMedia"));
        }
    }

Here is my xaml:

<ComboBox x:Name="Models_ComboBox"
      Width="110"
      Text="Model"
      ItemsSource="{Binding Models}"
      SelectedItem="{Binding SelectedModel}"
      DisplayMemberPath="Model"
      MouseDoubleClick="Models_ComboBox_MouseDoubleClick"
      SelectionChanged="Models_ComboBox_SelectionChanged"/>

Here are my VM properties:

private DataTable models;
public DataTable Models
{
    get { return models; }
    set
    {
        if (models != value)
        {
            models = value;
            OnPropertyChanged(nameof(Models));
        }
    }
}

and

private DataRowView selectedModel;
public DataRowView SelectedModel
{
    get { return selectedModel; }
    set
    {
        if (selectedModel != value)
        {
            selectedModel = value;
            if (value != null)
            {
                InitializeOptions(value["Model"].ToString());
            }
            OnPropertyChanged(nameof(SelectedModel));
        }
    }
}

As you can see, the ItemsSource and the SelectedItem of the ComboBox are bound to two different properties in the ViewModel. The ItemsSource is bound to a DataTable populated from a Database. Once the user selects a Model, then there are other option ComboBoxes that are populated based on that selection.

Fixed the problem myself. I had a line of code that was automatically setting the SelectedIndex of the ComboBox without me realizing.

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