DataGridComboBoxColumn how to return the selected value

1 Answer 568 Views
DataGrid
Rob
Top achievements
Rank 1
Rob asked on 14 Sep 2022, 10:37 AM

Hi There, I'm using the Telerik Datagrid for UWP and it is a pleasure to work with it. I am now developing a datagrid view with several comboboxes to select data from other Lists (Tables in sqlite) and I am struggling with the selected values. I have defined a combobox with the proper data to display but when I select a different record and try to update the change in the record the value is the same as when first initiated. How can i transfer the value? When I use a ordinary combobox the SelectedValuePath and the SelectedValue do the job but this is the datagrid and seems to be different. I searched the net and all questions and also your documentation but didn't find the answer. 

Here's some relevant code: 

XAML:

<Page
    x:Class="GolfComp.Views.TeamListPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:GolfComp.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" 
    xmlns:telerikGrid="using:Telerik.UI.Xaml.Controls.Grid"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <RelativePanel>
            <CommandBar x:Name="mainCommandBar" HorizontalAlignment="Stretch" IsEnabled="{x:Bind enableCommandBar}">
                <AppBarButton
                    Click="Insert_new_entry"
                    Icon="Add"
                    Label="New"
                    ToolTipService.ToolTip="New record"/>
                <AppBarButton
                    Click="Delete_Click"
                    Icon="Delete"
                    Label="Delete"
                    ToolTipService.ToolTip="Delete record" />
                <AppBarButton
                    Click="UpdateRecord_Click"
                    Icon="Refresh"
                    Label="Update"
                    ToolTipService.ToolTip="Update record" />
            </CommandBar>
            <StackPanel
                x:Name="newRecordStackPanel"
                Orientation="Horizontal"                
                RelativePanel.Below="mainCommandBar">
                <ComboBox x:Name="golfclubDropDown" Header="Homeclub" Margin="8,8,16,8" MinWidth="150"/>
                <ComboBox x:Name="klasseDropDown" Header="Competitie" Margin="8,8,16,8" MinWidth="150"/>
                <TextBox
                    x:Name="TeamNaamTextBox"
                    Header="Teamnaam"
                    PlaceholderText="teamnaam"
                    Margin="8,8,16,8"/>
                <AppBarButton x:Name="DeleteNewRecord" Click="DeleteNewRecord_Click" Icon="Cancel"/>
                <AppBarButton x:Name="SaveNewRecord" Click="SaveNewRecord_Click" Icon="Save"/>
            </StackPanel>
            <telerikGrid:RadDataGrid 
                AutoGenerateColumns="False"
                x:Name="Datagrid" 
                BorderThickness="0" 
                ColumnDataOperationsMode="Flyout" 
                GridLinesVisibility="None"
                GroupPanelPosition="Left" 
                RelativePanel.AlignLeftWithPanel="True"
                RelativePanel.AlignRightWithPanel="True"
                RelativePanel.Below="newRecordStackPanel"
                UserEditMode="Inline"
                SelectedItem="{x:Bind SelectedItem, Mode=TwoWay}">
                <telerikGrid:RadDataGrid.Columns>
                    <telerikGrid:DataGridComboBoxColumn PropertyName="Competitie" 
                                                        Header="Competitie"                                                         
                                                        ItemsSource="{x:Bind klasse}"
                                                        DisplayMemberPath="Competitie"
                                                        SelectedValuePath="Klasse_Id" />
                    <telerikGrid:DataGridNumericalColumn PropertyName="Speler1Id" Header="Speler 1"/>
                    <telerikGrid:DataGridNumericalColumn PropertyName="Speler2Id" Header="Speler 2"/>
                    <telerikGrid:DataGridNumericalColumn PropertyName="Speler3Id" Header="Speler 3" />
                    <telerikGrid:DataGridNumericalColumn PropertyName="Speler4Id" Header="Speler 4" />
                    <telerikGrid:DataGridNumericalColumn PropertyName="Speler5Id" Header="Speler 5" />
                    <telerikGrid:DataGridNumericalColumn PropertyName="Speler6Id" Header="Speler 6" />
                    <telerikGrid:DataGridTextColumn PropertyName="Naam" Header="Teamnaam" />
                </telerikGrid:RadDataGrid.Columns>
            </telerikGrid:RadDataGrid>
        </RelativePanel>
    </Grid>

</Page>

C#


namespace GolfComp.Views
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class TeamListPage : Page, INotifyPropertyChanged
    {
        ObservableCollection<SpelerModel> speler = new ObservableCollection<SpelerModel>();
        ObservableCollection<GolfclubModel> golfclub = new ObservableCollection<GolfclubModel>();
        ObservableCollection<TeamModel> team = new ObservableCollection<TeamModel>();
        ObservableCollection<CoachModel> coach = new ObservableCollection<CoachModel>();
        ObservableCollection<KlasseModel> klasse = new ObservableCollection<KlasseModel>();
        bool enableCommandBar = true;
        public TeamListPage()
        {
            this.InitializeComponent();
            newRecordStackPanel.Visibility = Visibility.Collapsed;
        }
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            GetData();
            wireUpDropdowns();
            if (Datagrid.ItemsSource == null)
            {
                Datagrid.ItemsSource = team;
            }
        }
        public void GetData()
        {
            string sql1 = "SELECT * from Speler";
            var spelerlijst = SqliteDataAccess.LoadData<SpelerModel>(sql1, new Dictionary<string, object>());
            spelerlijst.ForEach(x => speler.Add(x));

            string sql2 = "select * from Golfclub";
            var golfclublijst = SqliteDataAccess.LoadData<GolfclubModel>(sql2, new Dictionary<string, object>());
            golfclublijst.ForEach(x => golfclub.Add(x));

            string sql3 = "SELECT Team.Id, KlasseId, Speler1Id, Speler2Id, Speler3Id, Speler4Id, Speler5Id, Speler6Id, Team.Naam, Klasse_Id, Klasse_Naam, Klasse_Omschrijving from Team " +
                "INNER JOIN Klasse ON Klasse.Klasse_Id = Team.KlasseId;";
            var teamlijst = SqliteDataAccess.LoadData<TeamModel>(sql3, new Dictionary<string, object>());
            teamlijst.ForEach(x => team.Add(x));

            string sql4 = "select * from Coach";
            var coachlijst = SqliteDataAccess.LoadData<CoachModel>(sql4, new Dictionary<string, object>());
            coachlijst.ForEach(x => coach.Add(x));

            string sql5 = "select * from Klasse";
            var klasselijst = SqliteDataAccess.LoadData<KlasseModel>(sql5, new Dictionary<string, object>());
            klasselijst.ForEach(x => klasse.Add(x));

        }

        private void wireUpDropdowns()
        {
            golfclubDropDown.ItemsSource = golfclub;
            golfclubDropDown.DisplayMemberPath = "Naam";
            golfclubDropDown.SelectedValuePath = "Id";

            klasseDropDown.ItemsSource = klasse;
            klasseDropDown.DisplayMemberPath = "Competitie";
            klasseDropDown.SelectedValuePath = "Klasse_Id";
        }   
        private void Delete_Click(object sender, RoutedEventArgs e)
        {
            string sql = "delete from Teams where Id = @Id";
            try
            {
                Dictionary<string, object> parameters = new Dictionary<string, object>
                {
                    { "@Id", SelectedItem.Id }
                };
                SqliteDataAccess.DeleteData(sql, parameters);
                speler.Clear();
                GetData();
            }
            catch
            {
                MessageDialog messagedialog = new MessageDialog("Fout: Selecteer een record");
                _ = messagedialog.ShowAsync();

                return;
            }
        }
        private void UpdateRecord_Click(object sender, RoutedEventArgs e)
        {
            string sql = "update Team set KlasseId = @KlasseId, Speler1Id = @Speler1Id, Speler2Id = @Speler2Id, " +
                "Speler3Id = @Speler3Id, Speler4Id = @Speler4Id, Speler5Id = @Speler5Id, Speler6Id = @Speler6Id, " +
                "Naam = @Naam, CoachId = @CoachId, ClubId = @ClubId, PuntenVoor = @PuntenVoor, PuntenTegen = @PuntenTegen " +
                "where Id = @Id";
            try
            {
                Dictionary<string, object> parameters = new Dictionary<string, object>
                {
                    { "@Id",SelectedItem.Id },
                    { "@KlasseId", SelectedItem.Klasse_Id },
                    { "@Speler1Id", SelectedItem.Speler1Id},
                    { "@Speler2Id", SelectedItem.Speler2Id},
                    { "@Speler3Id", SelectedItem.Speler3Id},
                    { "@Speler4Id", SelectedItem.Speler4Id},
                    { "@Speler5Id", SelectedItem.Speler5Id},
                    { "@Speler6Id", SelectedItem.Speler6Id},
                    { "@Naam", SelectedItem.Naam},
                    { "@CoachId", SelectedItem.CoachId},
                    { "@ClubId", SelectedItem.ClubId},
                    { "@PuntenVoor", SelectedItem.PuntenVoor},
                    { "@PuntenTegen", SelectedItem.PuntenTegen}
                };
                SqliteDataAccess.SaveData(sql, parameters);
                speler.Clear();
                GetData();

                MessageDialog messagedialog = new MessageDialog("Succes: wijzigingen weggeschreven");
                _ = messagedialog.ShowAsync();
            }
            catch (Exception ex)
            {
                MessageDialog messagedialog = new MessageDialog(ex.Message);
                _ = messagedialog.ShowAsync();

                return;
            }
        }
        private void Insert_new_entry(object sender, RoutedEventArgs e)
        {
            enableCommandBar = false;
            newRecordStackPanel.Visibility = Visibility.Visible;
        }
        private void DeleteNewRecord_Click(object sender, RoutedEventArgs e)
        {           
            enableCommandBar = true;
            newRecordStackPanel.Visibility = Visibility.Collapsed;
        }
        private (bool isValid, TeamModel model) ValidateForm()
        {
            bool isValid = true;
            TeamModel model = new TeamModel();

            try
            {
                model.KlasseId = (int)klasseDropDown.SelectedValue;
                model.Speler1Id = 0;
                model.Speler2Id = 0;
                model.Speler3Id = 0;
                model.Speler4Id = 0;
                model.Speler5Id = 0;
                model.Speler6Id = 0;
                model.Naam = TeamNaamTextBox.Text;
                model.CoachId = 0;
                model.ClubId = (int)golfclubDropDown.SelectedValue;
                model.PuntenVoor = 0;
                model.PuntenTegen = 0;

            }
            catch
            {
                isValid = false;
            }
            return (isValid, model);
        }
        private void SaveNewRecord_Click(object sender, RoutedEventArgs e)
        {
            TeamModel model = new TeamModel();

            string sql = "insert into Team (KlasseId, Speler1Id, Speler2Id, Speler3Id, Speler4Id, Speler5Id, Speler6Id, Naam, CoachId, ClubId, PuntenVoor, PuntenTegen ) " +
                "values (@KlasseId, @Speler1Id, @Speler2Id, @Speler3Id, @Speler4Id, @Speler5Id, @Speler6Id, @Naam, @CoachId, @ClubId, @PuntenVoor, @PuntenTegen)";

            var form = ValidateForm();
            if (form.isValid == false)
            {
                MessageDialog messagedialog = new MessageDialog("foutieve invoer. Probeer het opnieuw");

                _ = messagedialog.ShowAsync();

                return;
            }
            if (TeamNaamTextBox.Text == "")
            {
                MessageDialog messagedialog = new MessageDialog("Vul alle velden in");

                _ = messagedialog.ShowAsync();

                return;
            }
            Dictionary<string, object> parameters = new Dictionary<string, object>
            {
                {"@KlasseId", form.model.KlasseId },
                {"@Speler1Id", form.model.Speler1Id },
                {"@Speler2Id", form.model.Speler2Id },
                {"@Speler3Id", form.model.Speler3Id },
                {"@Speler4Id", form.model.Speler4Id },
                {"@Speler5Id", form.model.Speler5Id },
                {"@Speler6Id", form.model.Speler6Id },
                {"@Naam", form.model.Naam },
                {"@CoachId", form.model.CoachId },
                {"@ClubId", form.model.ClubId },
                {"@PuntenVoor", form.model.PuntenVoor },
                {"@PuntenTegen", form.model.PuntenTegen }

            };
            SqliteDataAccess.SaveData(sql, parameters);
            //speler.Add(form.model);
            

            enableCommandBar = true;
            newRecordStackPanel.Visibility = Visibility.Collapsed;

            team.Clear();

            GetData();          

            wireUpDropdowns();
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName] string propertyName = null) =>
             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

        private TeamModel _selectedItem;

        public TeamModel SelectedItem
        {
            get => _selectedItem;
            set
            {
                if (_selectedItem != value)
                {
                    _selectedItem = value;
                    OnPropertyChanged();
                }
            }
        }
    }
}

1 Answer, 1 is accepted

Sort by
0
Polya
Telerik team
answered on 15 Sep 2022, 01:21 PM

Hi Rob,

I am happy to hear that you enjoy working with RadDataGrid.

From the provided source I am unsure what is the type of the property "Competitie" is. What is important is that the type of the property used for DataGridComboBoxColumn.PropertyName and the type of the object retrieved from the SelectedValuePath are the same. Also, you can take a look at our documentation about RadDataGrid.DataGridComboBoxColumn, where we list several custom scenarios and how to achieve them.

I've created a sample project containing a DataGridComboBoxColumn. Please find it attached.

Hope this helps. 

 

Regards,
Polya
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Rob
Top achievements
Rank 1
commented on 16 Sep 2022, 08:05 AM

Hi Polya,

Competition is a string combining Klasse_Naam + Klasse_Omschrijving to be displayed in the combobox. 

public string Klasse_Naam
        {
            get { return _klasse_naam; }
            set { _klasse_naam = value; }
        }
        private string _klasse_omschrijving;

        public string Klasse_Omschrijving
        {
            get { return _klasse_omschrijving; }
            set { _klasse_omschrijving = value; }
        }
        public string Competitie => $"{Klasse_Naam} {Klasse_Omschrijving}";

I Can't get your enclosed app working. I looked into it and decided to create a complete new test app based on the examples in your documentation. I hope it works.

Rob
Top achievements
Rank 1
commented on 16 Sep 2022, 11:31 AM

I have used your example and got the proper results. But... You use a static list containing a string of Items. I have the combobox working with the combined string competition from a ObserverableCollection filled by a table from my database. If I run the app the combobox is correctly filled with data from the database. E.g a Id-4 displays the record Id-4 and Competition description of Id-4 as the description. So Far everything is oké. But now I select another entry like entry with Id-2 the combobox displays now the description Competition for Id-2. This is correct. But now I want to update my database with Id-2 as I do with Dropbox-x.SelectedValue in a "normal" combobox. This is what's missing. I have the Selected Item from the datagrid but that's not the updated value. How do I get the updated value? From the ObserverableCollection? is the list updated?

Rob
Top achievements
Rank 1
commented on 16 Sep 2022, 03:53 PM

To make it even more clear, In normal operation of the grid the line is selected and the datatextbox can be edited by the user. When pressing "UpdateRecord_click" the new data is written to the database based on the selected row. This works fine. 
Polya
Telerik team
commented on 19 Sep 2022, 12:26 PM

Hi Rob,

Can you please provide a sample project demonstrating the case, so I can get a better understanding of your scenario. If you do not want to send the sample project in the forum you can open a support ticket and attach it there, or you can upload it to a github repo and provide the link here.

Looking forward to your reply.

Rob
Top achievements
Rank 1
commented on 19 Sep 2022, 05:43 PM

Hi Polya,

please find the file attached. I am quite new to this all so the easies way was attaching the file her in the forum. 

In the Assets folder you find a database with some data.

What I try to achieve is a TeamsListPage with several comboboxes to choose a Homeclub, Klasse, and six players and save it when filled to the database. I have created a relational database. Every table has it's Id as a primary key and is linked to another table by an integer that must be called when using the combobox. I hope this and my file makes it more clear. all this is part of an exam. The Exam assignment: "create an UWP app for a competition in your favorite sport and use a database" Ther is a bit more but that's not so important for you. So I decided to go for Sqlite and Telerik as base for my app. This is my first real adventure with C#. I am a beginner and learning.

Polya
Telerik team
commented on 20 Sep 2022, 10:54 AM

Hi Rob,

Thank you for providing the sample project. 
From what I can see your PropertyName and SelectedValuePath are of different types. Which means that when you choose a value from the combo the Id of klasse will be used to set the "Competetie"  property of your TeamModel.
Also the Competetie property does not have a setter, which means it cannot be set.

I suggest, instead of using Competetie property in your TeamModel, to use a property of type KlasseModel and override the ToString method of the KlasseModel to return the Competetie string instead. Then, because the property in the TeamModel is of type KlasseModel and the klasse ObservableCollection's items are of type KlasseModel when setting the property would work as expected, and because of the ToString override the KlasseModel value will be displayed as $"{Klasse_Naam} {Klasse_Omschrijving}".

  1. Override ToString() method in KlasseModel class:
    public class KlasseModel : INotifyPropertyChanged
    {
         // ... //
         public override string ToString()
         {
              return Competitie;
         }
    }
  2. Add property of type KlasseModel in your team model
    public class TeamModel : INotifyPropertyChanged
    {
    	// *** //	
    	private KlasseModel klasseModel;
            public KlasseModel KlasseModel
            {
                get { return klasseModel; }
                set
                {
                    if(klasseModel != value)
                    {
                        klasseModel = value;
                        OnPropertyChanged("KlasseModel");
                    }
                }
            }
    }
  3. Use the new property KlasseModel for the DataGridComboBoxColumn instead of "Competetie". Do not set DisplayMemberPath and SelectedValuePath, because the ToString override will do the trick
    <telerikGrid:DataGridComboBoxColumn PropertyName="KlasseModel"  
                                        Header="Competitie"       
                                        ItemsSource="{x:Bind klasse}"/>

 

I wasn't able to test your project due to the missing database, but I hope this does the trick.

Tags
DataGrid
Asked by
Rob
Top achievements
Rank 1
Answers by
Polya
Telerik team
Share this question
or