Home > Enterprise >  WPF C# Binding some combobox to one collection
WPF C# Binding some combobox to one collection

Time:12-06

I have my userControl element on the window.And now i must connect comboboxes inside this userControls to ObcervableCollection on the ViewModel. But i can't. I linked collections to items, but get the following error. When I change the selection in one combo box, I automatically get the changes for the others. How to unbind the SelectedItem of a combo box to use 1 collection for multiple items with independent selection.My control has this interface(for example). Thank's a lot.

<uielements:DeviceParametersControl Grid.Column="1"
    Margin="2,2"
    HorizontalAlignment="Stretch"
    VerticalAlignment="Stretch"
    EndColor="#3B191919"
    NumberOfSystem="2"
    MaxFaultPressureValue="{Binding DataContext.SelectedParameter[1].MaxFaultPressureValue, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
    MaxWorkPressureValue="{Binding DataContext.SelectedParameter[1].MaxWorkPressureValue, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
    MinWorkPressureValue="{Binding DataContext.SelectedParameter[1].MinWorkPressureValue, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
    TestTimeValue="{Binding DataContext.SelectedParameter[1].TestTimeValue, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
    PulseTimeValue="{Binding DataContext.SelectedParameter[1].PulseTimeValue, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
    PauseTimeValue="{Binding DataContext.SelectedParameter[1].PauseTimeValue, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
    PulsesCount="{Binding DataContext.SelectedParameter[1].PulsesCount, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
    PulsesAcceleration="{Binding DataContext.SelectedParameter[1].PulsesAcceleration, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
    Mode="{Binding DataContext.SelectedParameter[1].Mode,UpdateSourceTrigger=PropertyChanged, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
    StartColor="#3BFFFFFF"
    TestName="{Binding DataContext.SelectedParameter[1].Name, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
    UpdateDataToDbCommand="{Binding DataContext.UpdateDataToDbCommand,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
    UpdateDataToPlcCommand="{Binding DataContext.UpdateDataToPlcCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Control}}}"
    ItemsSource="{Binding DataContext.Parameters, Mode=OneWay,  RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
    DisplayMemberPath="Value"
    SelectedValuePath="Id"
    SelectedValue="{Binding DataContext.SelectedItem4Two, Mode=OneWayToSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">

</uielements:DeviceParametersControl>

CodePudding user response:

Use a different Object to each Components and selection like this :

XAML Code :

<Window x:Class="TestMVVMLight.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:TestMVVMLight"
    mc:Ignorable="d"
    DataContext="{Binding Main, Source={StaticResource Locator}}"
    Title="MainWindow" Height="450" Width="800">
    <Grid>
      <ComboBox HorizontalAlignment="Left" Margin="27,113,0,0" SelectedValue="{Binding SelectedParameter1}" VerticalAlignment="Top" Width="120" ItemsSource="{Binding Parameters}" DisplayMemberPath="Value"/>
      <ComboBox HorizontalAlignment="Left" Margin="171,113,0,0" SelectedValue="{Binding SelectedParameter2}" VerticalAlignment="Top" Width="120" ItemsSource="{Binding Parameters}" DisplayMemberPath="Value"/>
    </Grid>
 </Window>

ViewModel Code :

  public class MainViewModel : ViewModelBase
  {
    public MainViewModel()
    {
       ObservableCollection<Parameter> parameters = new ObservableCollection<Parameter>();
       for (int i = 0; i < 6; i  )
       {
         parameters.Add(new Parameter { Value = "Value "   i });
       }
       Parameters = parameters;
    }

    public ObservableCollection<Parameter> Parameters { get; set; }

    public Parameter SelectedParameter1 { get; set; }
    public Parameter SelectedParameter2 { get; set; }
  }

CodePudding user response:

    // XAML
// first control
ItemsSource="{Binding DataContext.Parameters, Mode=OneWay,  RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
SelectedValue="{Binding DataContext.SelectedItem4One, Mode=OneWayToSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">


// second control   
ItemsSource="{Binding DataContext.Parameters, Mode=OneWay,  RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
SelectedValue="{Binding DataContext.SelectedItem4Two, Mode=OneWayToSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">

// ViewModel
// all strings from database
public ICollectionView Parameters => this._model.Parameters.View;

// array for selected elements - it has 5 elements for each control 
public ObservableCollection<Parameters> SelectedParameter => this._model.SelectedParameter;


public object SelectedItem4One
    {
        set
        {
            if (value == null || value == _selectedItem4One) return;
            _selectedItem4One = value;
            this._model.GetParametersById(0, (int)_selectedItem4One);
        }
    }
//  - function from Model
public async Task GetParametersById(int index, int id)
    {
        try
        {
            var response = await _dataAccessService.DatabaseInterface
                .GetByIdAsync(id)
                .WithTimeout(TimeSpan.FromSeconds(TimeOutConnection));

            this.SelectedParameter[index] = response.FirstOrDefault() ?? new Parameters();

            OnPropertyChanged(new PropertyChangedEventArgs(nameof(SelectedParameter)));
        }
        catch (Exception e)
        {
            Message =
                "Ошибка получения набора параметров для выбранного рецепта из базы данных по Id.\n"   e.Message  
                e.InnerException;
            OnMessageChanged(new PropertyChangedEventArgs(nameof(Message)));
        }
    }
  • Related