0
votes

What I am trying to do is take the string out of a specific column in my DataGrid and display that string in the Combobox.Text property. I am using this code to do so:

var dataString = ((DataRowView)dgvMain.SelectedItem).Row["Column"].ToString();

I have placed a breakpoint on this to see what it was pulling, and it was the correct String that is contained as an item in the Combobox, but whenever I try to set it via Combobox.Text, the Combobox is empty. I have however set my Combobox to isEditable = True and ReadOnly = True and this method works, but selecting an item in the Collection will display System.Data.DataRowView, due to the Combobox being binded to my DataTable. I'll add the XAML to my Combobox as well:

<ComboBox x:Name="cboAlarmType" HorizontalAlignment="Left" Margin="138,256,0,0" VerticalAlignment="Top" Width="320" TabIndex="5"
              BorderBrush="Black" Background="White" ItemsSource="{Binding}" DisplayMemberPath="AlarmName" SelectedValuePath="AlarmName" 
              SelectedValue="{Binding Row.Column, ElementName=dgvMain}"/>

This method works in Textboxes and Checkboxes, but haven't seemed to figure it out for Comboboxes. Any guidance would be appreciated! :)

1
How are you populating your DataGrid? In WPF, you don't need to do ugly stuff like this. Just go to the items you're using to populate the DataGrid. Also, that multibinding in your DataTemplate looks like guesswork; you don't seem to be doing anything a multibinding would ever be used for. What are you populating the combobox with? - 15ee8f99-57ff-4f92-890c-b56153
I'm filling the DataGrid via a DataTable. The data in the DataTable is from a Select statement from my SQLite database. - RockGuitarist1
<DataTemplate><TextBlock Text="{Binding Column}" /></DataTemplate> should do the same as what you've got there. - 15ee8f99-57ff-4f92-890c-b56153
I guess the reason I left Multibinding StringFormat in there was because I was combining 2 columns at one time. You're right, it wouldn't be necessary for just one column. - RockGuitarist1
Oh, so DataRowView is a row in the datatable, sorry (derp). Is the ComboBox populating? I think what you want may be <ComboBox DisplayMemberPath="Column" SelectedValuePath="Column" SelectedValue="{Binding Row.Column, ElementName=dgvMain}" ... /> - 15ee8f99-57ff-4f92-890c-b56153

1 Answers

1
votes

It appears to me that your DataContext for the ComboBox must be the DataTable you're using to populate the DataGrid, because ItemsSource="{Binding}". I'm going to assume that it's the DataContext for the DataGrid as well, and that your goal is to have the ComboBox selection reflect the selected row in the DataGrid.

<DataGrid
    x:Name="dgvMain"
    ItemsSource="{Binding}"
    />
<ComboBox
    ItemsSource="{Binding}"
    DisplayMemberPath="Column"
    SelectedValuePath="Column"
    SelectedValue="{Binding SelectedItem.Row[Column], ElementName=dgvMain}"
    />

If you'd like the selection changes to go both ways -- so a change to the ComboBox selection changes the DataGrid selection -- that's easy:

<DataGrid
    x:Name="dgvMain"
    ItemsSource="{Binding}"
    SelectedValuePath="Column"
    SelectedValue="{Binding SelectedValue, ElementName=ColumnComboBox}"
    />
<ComboBox
    x:Name="ColumnComboBox"
    ItemsSource="{Binding}"
    DisplayMemberPath="Column"
    SelectedValuePath="Column"
    SelectedValue="{Binding SelectedItem.Row[Column], ElementName=dgvMain}"
    />

And here's a cleaner way to do the whole thing: First, write a viewmodel class in C#.

public class ViewModelbase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class MyViewModel : ViewModelbase
{
    public MyViewModel()
    {
        //  I populated my DataTable with "Row 1", "Row 2", etc.
        //  Naturally you'd use a value from your own data. 
        SelectedColumnValue = "Row 2";
    }

    #region SelectedColumnValue Property
    private String _selectedColumnValue = default(String);
    public String SelectedColumnValue
    {
        get { return _selectedColumnValue; }
        set
        {
            if (value != _selectedColumnValue)
            {
                _selectedColumnValue = value;
                OnPropertyChanged();
            }
        }
    }
    #endregion SelectedColumnValue Property

    public DataTable Data { get; protected set; }
}

Then use that SelectedColumnValue property to keep track of the selected value of "Column" for both controls. The bindings on the SelectedValue properties of the two controls will be two-way by default, because of framework stuff that makes it be that way (how's that for an explanation?). So if you change SelectedColumnValue programatically, the controls will update, and if the user changes the grid selection, the viewmodel property will be updated, which will in turn update the ComboBox -- and vice versa.

<DataGrid
    ItemsSource="{Binding Data}"
    SelectedValuePath="Column"
    SelectedValue="{Binding SelectedColumnValue}"
    />
<ComboBox
    ItemsSource="{Binding Data}"
    DisplayMemberPath="Column"
    SelectedValuePath="Column"
    SelectedValue="{Binding SelectedColumnValue}"
    />
<ComboBox
    ItemsSource="{Binding Data}"
    DisplayMemberPath="ShoeSize"
    SelectedValuePath="Column"
    SelectedValue="{Binding SelectedColumnValue}"
    />

Another wrinkle is that DisplayMemberPath and SelectedValuePath needn't be the same. Say we've got a "ShoeSize" column in Data, and we'd like to have those values displayed in another ComboBox. So we can do that. We're still using Column as a unique identifier for rows in Data, but we can tell the ComboBox to display some other column.