Search code examples
c#wpfmvvmdata-binding

WPF listview item that binds to combobox


I know this question may have been asked before but I can't find a solution for my problem and I will need some help.

What I want to accomplish :

I want to bind the exposed property Values of each item (ParameterValues) in my ListView to the ComboBox column and have the exposed property SelectedValue as selected item.

What I have done:

public class MyViewModel : MvvmTemplate //MvvmTemplate implements InotifyPropertyChanged
{
    private ObservableCollection<ParameterValues> _parameterValuesTest;

    public ObservableCollection<ParameterValues> ParameterValuesTest
    {
        get => _parameterValuesTest;
        set
        {
            if (value == null)
                return;
            _parameterValuesTest = value;
            RaisePropertyChanged(); 
        }
    }

    public MyViewModel()
    {
        Parameters = new List<ParametersModel>(GetParametersFromDatabase());
        ParameterValuesTest = new ObservableCollection<ParameterValues>();
        ParameterValuesTest.Clear();
        foreach(var param in parameters)
        {
            ParameterValuesTest.Add(new ParameterValues(param));
        }
    }
}

Parameters model :

public class ParametersModel:MvvmTemplate
{
    public ParametersModel()
    {
        Parameters = new Parameters();
    }

    public ParametersModel(Parameters Parameters)
    {
        Parameters = Parameters;
    }


    public Parameters Parameters { get; set; }

    public int Id
    {
        get => Parameters.Id;
        set
        {
            if (Parameters.Id == value)
            {
                return;
            }

            Parameters.Id = value;
            RaisePropertyChanged();
        }
    }
    
    
    public string Value1
    {
        get => Parameters.Value1;
        set
        {
            if (Parameters.Value1 == value)
            {
                return;
            }

            Parameters.Value1 = value;
            RaisePropertyChanged();
        }
    }
        
    public string Value2
    {
        get => Parameters.Value2;
        set
        {
            if (Parameters.Value2 == value)
            {
                return;
            }

            Parameters.Value2 = value;
            RaisePropertyChanged();
        }
    }
}

Parameters values model :

public class ParameterValues:MvvmTemplate
{
    public ParameterValues(ParametersModel parameter)
    {
        ParametersModel = parameter;
        Values = new ObservableCollection<string>
        {
            "Default Value",
            ParametersModel.Value1,
            ParametersModel.Value2
        };
    
        SelectedValue = Values.First();
    }


    public ParametersModel ParametersModel { get; set; }

    private ObservableCollection<string> _values;

    public ObservableCollection<string> Values
    {
        get => _values;
        set
        {
            if (_values == value)
                return;
            _values = value;
            RaisePropertyChanged();
        }
    }

    private string _selectedValue;

    public string SelectedValue
    {
        get => _selectedValue;
        set
        {
            if (_selectedValue == value)
                return;
            _selectedValue = value;
            RaisePropertyChanged();
        }
    }
}

XAML:

<ListView ItemsSource="{Binding Path=ParameterValuesTest}">
   <ListView.View>
      <GridView>
         <GridViewColumn Width="Auto" Header="Id" DisplayMemberBinding="{Binding ParametersModel.Id}"/>
         <GridViewColumn  Header="Value">
            <GridViewColumn.CellTemplate>
               <DataTemplate>
                  <Grid>
                     <ItemsControl ItemsSource="{Binding Values, NotifyOnTargetUpdated=True}" DisplayMemberPath="SelectedValue" Height="0"/>
                     <ComboBox ItemsSource="{Binding Values}" DisplayMemberPath="SelectedValue" SelectedValuePath="SelectedValue" SelectedValue="{Binding SelectedValue}" TextSearch.TextPath="SelectedValue" Text="{Binding SelectedValue}" IsEditable="True"/>
                  </Grid>
               </DataTemplate>
            </GridViewColumn.CellTemplate>
         </GridViewColumn>
      </GridView>
   </ListView.View>
</ListView>

Thanks in advance.


Solution

  • There are a few issues in your code.

    • In the parameters model, the assignment does not work, correct the parameter name.
      public ParametersModel(Parameters parameters)
      {
         Parameters = parameters;
      }
      
    • Remove the ItemsControl from the Grid, as it is hidden by the ComboBox or integrate it differently if you really need it, e.g. create rows or columns and place the controls in there.
    • The bindings in the ComboBox are wrong, you should bind to SelectedItem instead of using SelectedValue, since you have a collection of strings and not of a type that contains other properties that you want to bind to.
      <ComboBox ItemsSource="{Binding Values}" SelectedItem="{Binding SelectedValue}" Text="{Binding SelectedValue}" IsEditable="True"/>
      
    • Remove the TextSearch attached property, as it is not used here.