CheckBoxColumn with CheckBox Header

18 posts, 0 answers
  1. Morgan McCollough
    Morgan McCollough avatar
    34 posts
    Member since:
    May 2010

    Posted 01 Sep 2010 Link to this post

    I am a little confused. I have a grid with a column containing a boolean value. I have the checkbox column working with a single click, based on info from other forum posts. However, I am now trying to put a checkbox in the header to toggle that column for all visible rows. I implemented a click handler for that header checkbox to loop through cells in that column and click the checkbox, but it doesn't seem to work. Odd things happen like occasionally the last visible item will change, or sometimes some other seemingly random cell will become highlighted. Below is the basic code for the handler. Am I approaching this completely wrong? I wanted to do it at the UI level because I wanted all of my boolean columns to behave this way and didn't want to do it at the data level because I would have to basically provide a different implementation in every different grid.

    <telerikGrid:GridViewCheckBoxColumn DataMemberBinding="{Binding Path=ActiveFlag}" IsVisible="False" AutoSelectOnEdit="True" IsThreeState="False">
        <telerikGrid:GridViewCheckBoxColumn.Header>
            <CheckBox Content="Active" Click="HeaderCheckBox_Click" IsThreeState="False" />
        </telerikGrid:GridViewCheckBoxColumn.Header>
    </telerikGrid:GridViewCheckBoxColumn>

    private void HeaderCheckBox_Click(object sender, RoutedEventArgs e)
            {
                CheckBox cb = (CheckBox)sender;
                GridViewHeaderCell header = cb.ParentOfType<GridViewHeaderCell>();
     
                ReferenceGrid.BeginEdit();
                foreach (GridViewRowItem item in ReferenceGrid.ChildrenOfType<GridViewRowItem>())
                {
                    foreach (var cell in item.Cells)
                    {
                        if (cell.Column == header.Column)
                        {
                            if (cell is GridViewCell)
                            {
                                GridViewCell c = (GridViewCell)cell;
                                c.BeginEdit();
                                CheckBox checkbox = c.GetEditingElement() as CheckBox;
                                if (checkbox != null)
                                    checkbox.IsChecked = cb.IsChecked;
                                c.CommitEdit();
                            }
                            break;
                        }
                    }
                }
                ReferenceGrid.CommitEdit();
            }
  2. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 02 Sep 2010 Link to this post

    Hi Morgan McCollough,

    RadGridView enables virtualization by default and as a result when working directly with the UI elements (in your case when checking/unchecking CheckBoxes), this may result in unexpected for the end-user behavior. Meaning that some of the checked CheckBoxes may become unchecked and vise versus. That is why the recommended way is to use data items, for example you may expose a new property responsible for the state of those Check Boxes. 
    Another possible approach, depending on your requirements, may be to use RadGridView's GridVewSelectColumn
    If none of those is helpful for your application, please share more details about your requirements and project's settings, so that I can provide with a more suitable solution or a sample project if needed.


    Sincerely yours,
    Maya
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  3. DevCraft banner
  4. Morgan McCollough
    Morgan McCollough avatar
    34 posts
    Member since:
    May 2010

    Posted 02 Sep 2010 Link to this post

    I could experiment with the Select Column, but I suspect that I would have to do something like break the binding programmatically. The reason I was not using that is that the column is bound to a boolean value that has nothing to do with selection. The boolean is just an indicator that a particular product item has been purchased.
  5. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 03 Sep 2010 Link to this post

    Hi Morgan McCollough,

    If you want the CheckBox in the Column's Header just to mark all the items in the grid as "Purchased" for example, you may loop through all the items and set their property "IsPurchased" to "true". 
    For example:

    private void CheckBox_Checked(object sender, RoutedEventArgs e)
            {
                CheckBox headerCheckBox = e.OriginalSource as CheckBox;
                if(headerCheckBox.IsChecked == true)
                {
                    foreach(Player item in this.playersGrid.Items)
                    {
                        item.IsActive = true;
                    }
                }
            }

    Another possibility may be to create your custom column implementing the functionality you want as described in this blog post.


    Sincerely yours,
    Maya
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  6. Morgan McCollough
    Morgan McCollough avatar
    34 posts
    Member since:
    May 2010

    Posted 10 Sep 2010 Link to this post

    Thanks for the suggestion. I went ahead and tried the custom column, because there are other boolean properties in other grids that I would like to do the same thing with, and I wanted to avoid writing specific code-behind handlers on each one. Anyway, I tried the example in the blog post and used the following code, but the binding doesn't seem to work in TwoWay mode. The value seems to come up write when the grid is loaded, but the underlying property does not change when I click the checkbox (the DataMemberBinding in the xaml is indeed set to TwoWay). Any idea what might be going on here?

    BTW, I am on build 2010.2.812.1040.

    public override FrameworkElement CreateCellElement(Telerik.Windows.Controls.GridView.GridViewCell cell, object dataItem)
            {
                var cb = cell.Content as CheckBox;
     
                if (cb == null)
                {
                    cb = new CheckBox();
                    cb.IsThreeState = false;
                    cb.SetBinding(CheckBox.IsCheckedProperty, this.DataMemberBinding);
                    cell.Content = cb;
                }
     
                return cb;
            }
     
            public override FrameworkElement CreateCellEditElement(Telerik.Windows.Controls.GridView.GridViewCell cell, object dataItem)
            {
                var cb = cell.Content as CheckBox;
     
                if (cb == null)
                {
                    cb = new CheckBox();
                    cb.IsThreeState = false;
                    cb.SetBinding(PmcCheckBox.IsCheckedProperty, this.DataMemberBinding);
                    cell.Content = cb;
                }
     
                return cb;
            }

  7. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 13 Sep 2010 Link to this post

    Hello Morgan McCollough,

    I am senidng you a sample project illustrating how to create a custom CheckBoxColumn. It simulates the behavior of a GridViewSelectColumn with the difference that it is bound to a specific property but not to IsSelected property of the GridViewRow. You may use it as a reference and change it so that it reponds to your requirements. 
    In case you have any further questions or difficulties, do not hesitate to get back to us.
     

    All the best,
    Maya
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  8. Morgan McCollough
    Morgan McCollough avatar
    34 posts
    Member since:
    May 2010

    Posted 14 Sep 2010 Link to this post

    Thanks very much for the example. I hadn't thought to use the Expression library in writing the function to toggle the value in all the rows.

    Unfortunately, I still ran into some minor issues with the project you sent. I noticed that the XAML in the project didn't reference the new custom column, and once I changed that the example project basically had the same issues I had been seeing in my app. When the page first loads the checkboxes have the correct state, and you can toggle all of them using the header checkbox. However, once you change the state of one of the checkboxes in the grid, it seems to lose the binding or something and the header checkbox will no longer affect the state of the one that you have clicked. Does that make sense?

    I tried augmenting the custom column code you sent by adding an implementation for CreateCellEditElement that was practically identical to the CreateCellElement implementation. When I did this there were odd COM exceptions being thrown when I clicked on a checkbox in any one row. The only thing I could get to work to my satisfaction was using a DataTemplate (see below). I'm not sure how this was different than just implementing those 2 methods, but it seems to work.

    I also added an AutoRowEditBehavior that would cause the checkbox to be toggled automatically when the cell is clicked in order to get around that issue of having to click multiple times in order to toggle a checkbox in a grid row.

    protected override void OnDataMemberBindingChanged()
            {
                base.OnDataMemberBindingChanged();
                if (this.DataMemberBinding == null)
                    return;
                // Use a data template, because overriding the 2 create element functions like normal seems to cause odd problems when trying to make the checkbox editable with a single click
                StringBuilder sb = new StringBuilder();
                sb.Append("<DataTemplate ");
                sb.Append("xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' ");
                sb.Append("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' >");
                sb.AppendFormat("<CheckBox IsChecked='{{Binding Path={0}, Mode=TwoWay}}' HorizontalAlignment='Center' IsThreeState='False' />", this.DataMemberBinding.Path.Path);
                sb.Append("</DataTemplate>");
                var dt = (DataTemplate)XamlReader.Load(sb.ToString());
                this.CellTemplate = dt;
                this.CellEditTemplate = dt;
            }

  9. Morgan McCollough
    Morgan McCollough avatar
    34 posts
    Member since:
    May 2010

    Posted 14 Sep 2010 Link to this post

    Scratch that. I am not sure where that COM exception was coming from (I can't reproduce it). Also, I think I was wrong about that binding getting disconnected. I think I just confused myself on that, because the column I was looking at only had a OneWay binding set.

    The problem that is happening is if I override those 2 methods, I get a value outside of expected range exception when I expand the row details and then click the checkbox in the row. The exception seems to occur when BeginEdit is called as part of the AutoRowEditBehavior. Note that this does NOT happen if I use a DataTemplate as outlined above.
  10. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 20 Sep 2010 Link to this post

    Hi Morgan McCollough,

    Firstly, please excuse me for the late response. 
    I am sending you the sample project with some changes made so that it is a bit clearer and more applicable. Mainly, what needs to be done is to set the Mode of the Binding for that custom column to "TwoWay".
    Please let me know if it helps. In case it does not, I would need more information about your application and its settings. It would be great if it is possible to send me a sample project with your exact requitements via support ticket. 
     

    Sincerely yours,
    Maya
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  11. Morgan McCollough
    Morgan McCollough avatar
    34 posts
    Member since:
    May 2010

    Posted 21 Sep 2010 Link to this post

    I got the TwoWay binding working. That was definitely my mistake. Thanks for the updated example, but my column still suffers from the same out of range exception unless I implement it using the template method I mentioned.

    Also, when I try using your method the binding doesn't seem to cause the underlying data to change in my app even though it seems to in yours. I think it has to do with the edit mode or selection mode (I am using cell selection), because I can't find any other real differences between your example and mine other than the fact that I am using the 8/12 build. I do notice in both my grid and yours that when you click in the cell but outside the checkbox itself, it seems to put the cell in edit mode and the checkbox gets smaller as if it is a different rendered control.

    The upshot is that I have this mostly working, but I had to use the template method and an Auto-edit behavior to put the cell in edit mode during the MouseLeftButtonDown event.

    I don't suppose there is a way to just put the cell perpetually in edit mode when using a checkbox?
  12. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 24 Sep 2010 Link to this post

    Hi Morgan McCollough,

    I have tested my sample project and the underlaying data is updated as expected, no matter of the edit mode or the selection unit. As for the skipping the visual state of edit mode of that custom column, you may set its property IsReadOnly to "True". I am sending you the updated sample project that introduces that setting and defines a RowDetailsTemplate. 


    Kind regards,
    Maya
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  13. Anthony
    Anthony avatar
    24 posts
    Member since:
    Feb 2011

    Posted 23 Aug 2011 Link to this post

    Hello, can I have this sample project of yours in VB.Net? I have converted it using the telerik Code Converter but there are some parts of codes I cant understand.

    Any help would be appreciated. Thanks.
  14. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 24 Aug 2011 Link to this post

    Hi Mark,

    May you shed some more light on the exact problems you encountered so that we could concentrate on them right away ? Is there any particular part of the code that you cannot convert ? 


    Kind regards,
    Maya
    the Telerik team

    Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>

  15. Anthony
    Anthony avatar
    24 posts
    Member since:
    Feb 2011

    Posted 24 Aug 2011 Link to this post

    It will be a waste of time for me fixing the converted code Maya. Would it be possible to get the VB.Net version of the code posted here in this thread?

    Anyway, here is my scenario... I have a RadGridView with row details, I have a field "isChecked" as boolean that binds in a checkbox, this field will determine who is the checked items then it will mark the data to 'true' when selected. Now, I am able to do that scenario... The thing is, I also added checkbox for the header template... The main problem is that the checkbox header is not firing an event. I would like to fire an event because I want to collect all those items that is marked "isChecked =  True"

    Kindly help me with this matter... Thanks.
  16. Chen
    Chen avatar
    18 posts
    Member since:
    Apr 2012

    Posted 20 Apr 2012 Link to this post

    Hi Maya,

    I tried your code and got the "{System.StackOverflowException}" exception at the setter of the "Header" property in the "CustomCheckBoxColumn.cs" file. Do you have any idea?

    By the way, I included this customized checkbox column in the "telerik:GridViewColumnCollection" tag in the "UserControl.Resources" of the xaml file as following:
    <UserControl.Resources>        
        <telerik:GridViewColumnCollection x:Name="CustomColumnDefinition">            
            <my:CustomCheckBoxColumn DataMemberBinding="{Binding IsChecked, Mode=TwoWay}" IsReadOnly="True" />            
            <telerik:GridViewDataColumn DataMemberBinding="{Binding Path=otherproperty1}" Header="Resource Name" />           
            <telerik:GridViewDataColumn DataMemberBinding="{Binding Path=otherproperty2}" Header="Resource Description"/>          
            <telerik:GridViewDataColumn DataMemberBinding="{Binding Path=otherproperty3}" Header="IPType" />       
        </telerik:GridViewColumnCollection> 
    </UserControl.Resources>

    Thanks for any suggestions.

    Some suggestions:
    1. In you sample code, I'd like to see the functions of :

              a. If all the checkboxes in the column are checked, the checkbox in the header cell should be checked as well
              b. If any of the checkboxes in the column is/are unchecked, the checkbox in the header cell should be unckecked if it is checked.

    2.    In the "SelectOrDeselectAllItems" method in the "CustomCheckBoxColumn.cs" file, if you change the "Player" type in the foreach loolp to "var", this class can be used for any types.

     

    SelectOrDeselectAllItems

  17. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 21 Apr 2012 Link to this post

    Hi Chen,

    You can subscribe to the Checked event of the CheckBox in CreateCellElement method and verify whether all items in the Items collection have the corresponding property set to "true". Once you confirm that all of them are 'True', you can set IsChecked of the Header CheckBox to "true". The same approach could be used in the reverse case - in the Checked event handler, if a single item's property is set to 'false', set header's CheckBox to 'false'.
    Considering the second requirement, I am not quite sure what is the question here. Did you not managed to implement the code for different than 'Player' type ?  

    Regards,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  18. Chen
    Chen avatar
    18 posts
    Member since:
    Apr 2012

    Posted 23 Apr 2012 Link to this post

    Hi Maya,

    Thanks for the reply.

    Did you have any suggestions about the "{System.StackOverflowException}" exception?
    This is my top priority concern.

    Thanks.
  19. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 23 Apr 2012 Link to this post

    Hello Morgan,

    The thing is that I could not get the exception you mentioned. Is there anything more specific that you do in order to get it ? Why do you need such column collection defined in the Resources section ?   

    Greetings,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Back to Top
DevCraft banner