wpfmvvmcomboboxcaliburn.microitemscontrol

ItemsControl that contains bound ComboBox in ItemTemplate (WPF MVVM with Caliburn.Micro)


I'm stuck with a problem to select one item in a single combo box from a list of combo boxes bound in a ItemTemplate. When I select a value in one, that value gets updated in all of them. It resembles this problem ItemsControl that contains bound ComboBox in ItemTemplate but I can't get what I'm missing. Can someone help, please?

If need more code for clarification, just ask :) Thank you!

ItemsControl:

<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto"
          VerticalScrollBarVisibility="Auto">
<ItemsControl x:Name="InputsList"
              Margin="15 10 10 5">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Components:InputUCView/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

UserControl (with combobox)

<ComboBox x:Name="PdfListCombo"
      Style="{DynamicResource conditionalComboBox}"
      Grid.Column="1" Grid.Row="0"
      Margin="2 5 5 2" Text="Select pdf"
      ItemsSource="{Binding RelativeSource={
                RelativeSource AncestorType={
                x:Type ItemsControl}},
                Path=DataContext.PdfListCombo}"
      SelectedItem="{Binding RelativeSource={
                RelativeSource AncestorType={
                x:Type ItemsControl}},
                Path=DataContext.SelectedPdfName, Mode=TwoWay}"/>

parts in question from ViewModel

private BindableCollection<InputModel> _inputsList;

public BindableCollection<InputModel> InputsList
{
   get
     {
    
       _inputsList = new(inputsList);
       return _inputsList;
     }
  set
    {
      _inputsList = value;
      NotifyOfPropertyChange(() => InputsList);
    }
  }


    private BindableCollection<string> _pdfListCombo;

    public BindableCollection<string> PdfListCombo
    {
        get
        {
            //_pdfListCombo ??= new();
            foreach (var item in inputsList)
            {
                List<string> pdfFiles = new();
                foreach (var pdf in item.PdfNames)
                {
                    pdfFiles.Add(Path.GetFileName(pdf));
                }
                _pdfListCombo=new(pdfFiles);
            }
            return _pdfListCombo;
        }
        set
        {
            _pdfListCombo = value;
            NotifyOfPropertyChange(() => PdfListCombo);
        }
    }

    private string _selectedPdfName;

    public string SelectedPdfName
    {
        get
        {
            return _selectedPdfName;
        }
        set
        {
            _selectedPdfName = value;
            NotifyOfPropertyChange(() => SelectedPdfName);
        }
    }

Solution

  • By your code

    <ComboBox x:Name="PdfListCombo"
          Style="{DynamicResource conditionalComboBox}"
          Grid.Column="1" Grid.Row="0"
          Margin="2 5 5 2" Text="Select pdf"
          ItemsSource="{Binding RelativeSource={
                    RelativeSource AncestorType={
                    x:Type ItemsControl}},
                    Path=DataContext.PdfListCombo}"
          SelectedItem="{Binding RelativeSource={
                    RelativeSource AncestorType={
                    x:Type ItemsControl}},
                    Path=DataContext.SelectedPdfName, Mode=TwoWay}"/>
    

    Your ComboBox binds the ItemsSource to the property PdfListCombo of the DataContext of the first found ItemsControl parent.
    And ComboBox binds the SelectedItem to the property SelectedPdfName of the DataContext of the first found ItemsControl parent...........
    enter image description here
    TwoWays binding to same property of same object, that's caused your problem.