How do I get default ComboBox behavior in a DataGridTemplate column?

4 posts, 0 answers
  1. Matthew
    Matthew avatar
    7 posts
    Member since:
    Sep 2017

    Posted 12 Apr Link to this post

    In my RadDataGrid, I have to use a DataGridTemplateColumn because the Itemssource of my combobox is a collection that is a property of the object represented by the grid row. I've got it working except for the fact that the combo box is always editable. In other words, the box and dropdown arrow are always visible. 

    In a regular combobox column on a RadDataGrid the combo box is not visible unless you double click on the column. Until you click, the column just displays the selected item. In my columns, the box and dropdown arrow are always visible, before and after you click in or out of the column.
    How can I change this to the typical behavior? I want the user to have to click in the column before the box and dropdown arrow become visible. Before that, the column just display the selected item. Thanks for your help.

    <tg:DataGridTemplateColumn  SizeMode="Auto">
            <tg:DataGridTemplateColumn.CellContentTemplate>
                <DataTemplate>
                    <ComboBox Width="220"
                              ItemsSource="{Binding Path=ItemCategory.Items, Mode=OneWay}"
                              SelectedItem="{Binding Products, Mode=TwoWay}"
                              SelectedValue="{Binding Products.Id, Mode=OneWay}"
                              SelectedValuePath="Id"
                              DisplayMemberPath="ItemName">
                    </ComboBox>
            </DataTemplate>
            </tg:DataGridTemplateColumn.CellContentTemplate>
            <tg:DataGridTemplateColumn.Header>
                <TextBlock.Text = "Item Category"/>
            </tg:DataGridTemplateColumn.Header>
        </tg:DataGridTemplateColumn>

  2. Lance | Principal TSE
    Admin
    Lance | Principal TSE avatar
    1043 posts

    Posted 15 Apr Link to this post

    Hello Matthew,

    This in unavoidable when using a TemplateColumn. This is because TemplateColumn doesn't have an "Edit mode" and will always display the content you've set in the CellContentTemplate. By having an "editor" in the CellContentTemplate (a ComboBox that can change the value at any time), it will always appear to be in "edit mode".

    The other column types have two view modes; one for display (customizable through the CellContentTemplate) and editing (customizable through the CellEditorStyle). We swap out these containers depending if that cell is in edit mode, so the editor is only in the Visual Tree at the approriate time.

    I have two options you can consider:


    Options

    ComboBoxColumn Option (recommended)

    Use a ComboBoxColumn, which was designed for this specific scenario and we automatically handle displaying the correct string for the selected item that matches the ID in the parent data context.

    ItemsSource

    Because you need a collection on the row's data item, there are two approaches you can take:

    1. Use the built-in support for this scenario with the ItemsSourcePath property:

    <grid:DataGridComboBoxColumn PropertyName="Id"
                      SelectedValuePath="Id"
                      DisplayMemberPath="ItemName"
                      ItemsSourcePath="Items"/>

    Note: Since you haven't shared the models, I can only guess that the path is Items, you can experiment to set the correct path. ITemsSourcePath expected that value to be a property available in the data item's scope. See the ItemsSourcePath documentation.


    Custom ItemsSource Pointer

    If the ItemsSourcePath doesn't work for you, you can always use an ElementName binding approach to directly access the collection. This is done via DataGrid's SelectedItem to access the row's data object.

    I've attached an example of this you can try at runtime. For your convenience, here's the gist of it:

    Model for the DataGrid's rows

    public class DataItem
    {
        public string Item { get; set; }
        public string Brand { get; set; }
     
        public List<BrandItem> Brands { get; } = new List<BrandItem>
        {
            new BrandItem("Honda"), new BrandItem("Volvo"), new BrandItem("Mercedes"),
            new BrandItem("Scott"), new BrandItem("Giant"), new BrandItem("Trek")
        };
    }

    Notice the ItemsSource comes right from the selected row that contains the newly visualized ComboBox

    <grid:RadDataGrid x:Name="DataGrid"
                ItemsSource="{Binding Items}"
                UserEditMode="Inline"
                AutoGenerateColumns="False">
        <grid:RadDataGrid.Columns>
            <grid:DataGridTextColumn PropertyName="Item" />
     
            <grid:DataGridComboBoxColumn PropertyName="Brand"
                               SelectedValuePath="BrandName"
                               DisplayMemberPath="BrandName"
                               ItemsSource="{Binding ElementName=DataGrid, Path=SelectedItem.Brands}"/>
        </grid:RadDataGrid.Columns>
    </grid:RadDataGrid>


    If you are using the TemplateColumn for additional styling options, you can easily access the ComboBox through the CellEditorStyle

    <grid:DataGridComboBoxColumn PropertyName="Brand"
                      SelectedValuePath="BrandName"
                      DisplayMemberPath="BrandName"
                      ItemsSource="{Binding ElementName=DataGrid, Path=SelectedItem.Brands}">
        <grid:DataGridComboBoxColumn.CellEditorStyle>
            <Style TargetType="ComboBox">
                <Setter Property="Foreground" Value="Red"/>
            </Style>
        </grid:DataGridComboBoxColumn.CellEditorStyle>
    </grid:DataGridComboBoxColumn>


    Template Column

    If you mustto stay with the TemplateColumn, you'll need to build out that DataTemplate to support switching between "display mode" and "edit mode". You can either design a custom style that has triggers on whether the comboBox has focus and show/hide the dropdown button accordingly. 

    Keep in mind that this still has implications that you'll have a ComboBox in the visual tree at all times, on all the rows. If you're using event handlers or other things that need lifecycle considerations, you might want to manage event handlers whent he ComboBox is added or removed from the visual tree.

    That being said, I strongly recommend using ComboBoxColumn.


    Further Assistance

    Assistaning with the TemplateColumn option is outside the scope of support, however I can assist with the built-in features. If you're still having trouble with the ComboBox column, please reply back with my demo project updated to reflect the problem you're having and I'll in vestigate further.

    Note that only support tickets allow attaching a ZIP file, you'll need to host the project somewhere else (e.g. OneDrive) and share a download link with me.

    Regards,
    Lance | Technical Support Engineer, Principal
    Progress Telerik
    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 Feedback Portal and vote to affect the priority of the items
  3. Matthew
    Matthew avatar
    7 posts
    Member since:
    Sep 2017

    Posted 15 Apr in reply to Lance | Principal TSE Link to this post

    Thanks, Lance. Your post was a great help. I was able to get the ElementName binding approach working. 

    I'm only having one slight issue now. Sometimes after I have selected an item in one combo box column, and I then select an item in the combo box column next to it, the item selected in the first combo box disappears. If I click out of the row, it reappears. Is there anything I can do to stop that behavior?  (It doesn't appear to be affecting the values of the objects themselves. It seems to be just a UI issue. And there doesn't seem to be a pattern. It occurs randomly.)

    Thanks!

  4. Lance | Principal TSE
    Admin
    Lance | Principal TSE avatar
    1043 posts

    Posted 16 Apr Link to this post

    Hello Matthew,

    I'm happy that I was able to assist. 

    Regarding the disappearing item, I'm not able to reproduce it. Like you said it's probably a transient UI issue. 

    I can escalate the problem to the UWP development if you take the following steps:

    1. Create a small standalone app that reprodcues the problem.
    2. Go to the UI for UWP Feedback Portal and click the "Report a Bug" button at the top right
    3. Attach the project and provide a summary of the steps to reproduce the issue

    Come back here and let me know what the ticket number is or just give me the URL, I'll talk to the developers of the DataGrid directly.

    Regards,
    Lance | Technical Support Engineer, Principal
    Progress Telerik
    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 Feedback Portal and vote to affect the priority of the items
Back to Top