0
votes

In my WPF application using MVVM, I have one DataGrid (dgSelectCase) filled with a bound ObservableCollection from my ViewModel. A Button appears in the first column that, when clicked, should add the selected row to the second DataGrid (dgCaseSelected).

The View DataContext is bound to the ViewModel in its code behind, and I know it works because the other Controls on the page (Comboboxes, Textboxes, etc.) work perfectly. The "Add" Button Command in dgSelectCase is bound to the AddTo method in the ViewModel and the "Remove" Button Command in dgCaseSelected is bound to the RemoveFrom method in the ViewModel.

The "Add" Button is not working, but, more importantly, it looks like I have selection Binding issues in the dgSelectCase DataGrid because I get a red box around the DataGrid when I click on a row. Where have I gone wrong? Thanks for any and all help, as I'm still learning.... slowly :). Following are Code Snippets.

XAML

        <DataGrid>
            <DataGrid.Columns>
            <DataGridTemplateColumn Header="Select">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button Content="Add" Command="{Binding AddTo}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Header="Fac ID #" Binding="{Binding FacilityIDNum}"/>
            <DataGridTextColumn Header="OP Case #" Binding="{Binding CaseBookingNum}"/>
            <DataGridTextColumn Header="Booking Type #" Binding="{Binding BookingTypeNum}"/>
            <DataGridTextColumn Header="Booking Type" Binding="{Binding BookingType}"/>
            </DataGrid.Columns>
        </DataGrid>

        <DataGrid x:Name="dgCaseSelected"
              AutoGenerateColumns="False"
              ItemsSource="{Binding DGCaseBookingsSelected}"
              >
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Select">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Content="Remove" Command="{Binding RemoveFrom}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Header="Fac ID #" Binding="{Binding FacilityIDNum}"/>
                <DataGridTextColumn Header="OP Case #" Binding="{Binding CaseBookingNum}"/>
                <DataGridTextColumn Header="Booking Type #" Binding="{Binding BookingTypeNum}"/>
                <DataGridTextColumn Header="Booking Type" Binding="{Binding BookingType}"/>
            </DataGrid.Columns>
        </DataGrid>

VIEWMODEL

    private ObservableCollection<DGCaseBookings> _dgCaseBookingsList;
    private ObservableCollection<DGCaseBookings> _dgSelectedCaseBookings;
    private ObservableCollection<DGCaseBookings> _dgCaseBookingsSelected;

    public ObservableCollection<DGCaseBookings> DGCaseBookingsList
    {
        get { return _dgCaseBookingsList; }
        set
        {
            SetProperty(ref _dgCaseBookingsList, value, () => DGCaseBookingsList);
        }
    }

    public ObservableCollection<DGCaseBookings> DGSelectedCaseBookings
    {
        get { return _dgSelectedCaseBookings; }
        set
        {
            SetProperty(ref _dgSelectedCaseBookings, value, () => DGSelectedCaseBookings);
        }
    }

    public ObservableCollection<DGCaseBookings> DGCaseBookingsSelected
    {
        get { return _dgCaseBookingsSelected; }
        set
        {
            SetProperty(ref _dgCaseBookingsSelected, value, () => DGCaseBookingsSelected);
        }
    }

    public CMBookingSelectVM() : base()
    {
        DGCaseBookingsList = new ObservableCollection<DGCaseBookings>();
        DGCaseBookingsSelected = new ObservableCollection<DGCaseBookings>();
    }

    private void fillDGCaseBookingswithFacility()
    {
        using (MySqlConnection con = new MySqlConnection(dbConnectionString))
        {
            DGCaseBookingsList = new ObservableCollection<DGCaseBookings>();
            con.Open();
            string Query = ///SELECT STATEMENT WORKS FINE///
            MySqlCommand createCommand = new MySqlCommand(Query, con);
            MySqlDataReader dr = createCommand.ExecuteReader();
            int count = 1;
            while (dr.Read())
            {
                int FacilityIDNum = dr.GetInt32(0);
                int CaseBookingNum = dr.GetInt32(1);
                int BookingTypeNum = dr.GetInt32(2);
                string BookingType = dr.GetString(3);
                DGCaseBookings dgcb = new DGCaseBookings(count, FacilityIDNum, CaseBookingNum, BookingTypeNum, BookingType);
                DGCaseBookingsList.Add(dgcb);
                count++;
            }
            con.Close();
        }
    }

    public void AddTo(DGCaseBookings dgcb)
    {
        if (dgcb != null)
        {
            DGCaseBookingsSelected.Add(dgcb);
            DGCaseBookingsList.Remove(dgcb);
        }
    }

    public void RemoveFrom(DGCaseBookings dgcb)
    {
        if (dgcb != null)
        {
            DGCaseBookingsList.Add(dgcb);
            DGCaseBookingsSelected.Remove(dgcb);
        }
    }
2

2 Answers

0
votes

First of all, you didn't mentioned in your code how you are trying to bind the selected items property of the datagrid to your collection (as a matter of facts you are actually didn't even set the itemsource for the first datagrid), and i think you didn't do that since you actually can't bind the SelectedItems property of the datagrid since it's a readonly property. From now on you have only 2 choice. Find a workaround to send the selected items to your viewmodel, or work on a single row. As for the second approach you can simply do this:

    <DataGrid ItemsSource="{Binding DGCaseBookingsList}" SelectedItem="{Binding MyItem}" SelectionMode = "Single" SelectionUnit="FullRow">
        <DataGrid.Columns>
        <DataGridTemplateColumn Header="Select">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Button Content="Add" Command="{Binding AddTo}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="Fac ID #" Binding="{Binding FacilityIDNum}"/>
        <DataGridTextColumn Header="OP Case #" Binding="{Binding CaseBookingNum}"/>
        <DataGridTextColumn Header="Booking Type #" Binding="{Binding BookingTypeNum}"/>
        <DataGridTextColumn Header="Booking Type" Binding="{Binding BookingType}"/>
        </DataGrid.Columns>
    </DataGrid>

in your VM delete DGSelectedCaseBookings and add the following:

private DGCaseBookings myItem = new DGCaseBookings();
public DGCaseBookings MyItem
{
    get { return myItem; }
    set
    {
        SetProperty(ref myItem, value, () => MyItem);
    }
}

From there you will handle this object using the command of your buttons. Just be sure to implement INotifyPropertyChanged or you won't see any change in your UI.

If you aim to a multiple selection, then the easiest way is to work on the selection changed event of your datagrids. From there you can do something like this.

private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
     MyVM vm = this.DataContext as MyVM;
     DataGrid s = sender as DataGrid;
     vm.DGSelectedCaseBookings = s.SelectedItems;
}
0
votes

In background of this you can setup the event when you click on button and add the current row (like param of the event). Take the current row select it from the datasource/ObservableCollection and add it in another dataset e.g _dgSelectedCaseBookings.

After that you can refresh the new _dgSelectedCaseBookings on UI.