Introduction to the problem
I have a DataGrid that has a DataGridTemplateColumn, the template of which contains a ComboBox control. My problem is that when the displayed member of the selected item is too long to fit into the width of the ComboBox, then the width of the ComboBox does not expand to accommodate the width of the displayed memeber, as it does if the same ComboBox is not in the DataGrid.
Working Example
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        Title="MainWindow" Height="350" Width="525">
   <StackPanel>
      <DataGrid Height="150"
                Margin="0,4,0,0"
                CanUserAddRows="False"
                CanUserDeleteRows="False"
                CanUserReorderColumns="False"
                CanUserResizeColumns="False"
                HorizontalAlignment="Stretch"
                ColumnWidth="SizeToCells"
                HeadersVisibility="Column"
                AutoGenerateColumns="False"
                RowHeaderWidth="0"
                IsSynchronizedWithCurrentItem="True"
                ItemsSource="{Binding Path=Entities, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
                SelectedItem="{Binding Path=SelectedEntity}"
                SelectionUnit="FullRow"
                SelectionMode="Single">
         <DataGrid.Resources>
            <DataTemplate x:Key="TextBox_Template">
               <TextBox Text="{Binding Path=Text}" Margin="2,2,2,2"/>
            </DataTemplate>
            <DataTemplate x:Key="ComboBox_Template">
               <ComboBox Margin="2,2,2,2"
                         Width="Auto"
                         ItemsSource="{Binding Path=DataContext.AvailableActions,
                                               Mode=OneTime,
                                               RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                         SelectedValue="{Binding Path=Action, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                         SelectedValuePath="Key"
                         DisplayMemberPath="Value"
                         IsEditable="False"
                         IsSynchronizedWithCurrentItem="False"/>
            </DataTemplate>
         </DataGrid.Resources>
         <DataGrid.Columns>
            <DataGridTemplateColumn Width="*"
                                    CanUserReorder="False" CanUserResize="False"
                                    CellTemplate="{StaticResource TextBox_Template}"
                                    Header="Text Field"/>
            <DataGridTemplateColumn Width="Auto"
                                    CanUserReorder="False" CanUserResize="False"
                                    CellTemplate="{StaticResource ComboBox_Template}"
                                    Header="Action"/>
         </DataGrid.Columns>
      </DataGrid>
      <Separator Margin="0,5,0,5"/>
      <StackPanel Orientation="Horizontal">
         <Button Content="Add Row" Margin="2,2,2,2"
                 Command="{Binding AddRowCommand}"/>
         <Button Content="Remove Row" Margin="2,2,2,2"
                 Command="{Binding RemoveRowCommand}"/>
      </StackPanel>
      <Separator Margin="0,5,0,5"/>
      <ComboBox Width="Auto"
                ItemsSource="{Binding Path=AvailableActions}"
                SelectedValuePath="Key"
                DisplayMemberPath="Value"
                IsEditable="False"
                HorizontalAlignment="Left"/>
   </StackPanel>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
namespace WpfApplication1
{
   /// <summary>
   /// Interaction logic for MainWindow.xaml
   /// </summary>
   public partial class MainWindow : Window, INotifyPropertyChanged
   {
      public event PropertyChangedEventHandler PropertyChanged;
      public static Dictionary<ActionType, string> AvailableActions { get; set; }
      public EntityClass SelectedEntity { get; set; }
      public ObservableCollection<EntityClass> Entities { get; set; }
      public AddRowCommandClass AddRowCommand { get; set; }
      public RemoveRowCommandClass RemoveRowCommand { get; set; }
      static MainWindow()
      {
         AvailableActions = new Dictionary<ActionType, string>()
         {
            {ActionType.Accept,   "Accept the text"},
            {ActionType.Reject,   "Reject the text"},
            {ActionType.Refer,    "Refer the text"},
            {ActionType.Postpone, "Postpone the text"},
         };
      }
      public MainWindow()
      {
         Entities = new ObservableCollection<EntityClass>()
         {
            new EntityClass() { Text = "First Example Text",  Action = ActionType.Accept},
            new EntityClass() { Text = "Second Example Text", Action = ActionType.Reject},
            new EntityClass() { Text = "Third Example Text",  Action = ActionType.Refer},
         };
         AddRowCommand = new AddRowCommandClass(this);
         RemoveRowCommand = new RemoveRowCommandClass(this);
         InitializeComponent();
      }
      public enum ActionType
      {
         Accept,
         Reject,
         Refer,
         Postpone,
      }
      public class EntityClass
      {
         public string Text { get; set; }
         public ActionType Action { get; set; }
      }
      public class AddRowCommandClass : ICommand
      {
         public event EventHandler CanExecuteChanged;
         private MainWindow _window;
         public AddRowCommandClass(MainWindow window)
         {
            _window = window;
         }
         public bool CanExecute(object parameter)
         {
            return true;
         }
         public void Execute(object parameter)
         {
            _window.Entities.Add(new EntityClass() { Text = "Hello World!", Action = ActionType.Postpone });
         }
      }
      public class RemoveRowCommandClass : ICommand
      {
         public event EventHandler CanExecuteChanged;
         private MainWindow _window;
         public RemoveRowCommandClass(MainWindow window)
         {
            _window = window;
         }
         public bool CanExecute(object parameter)
         {
            return _window.SelectedEntity != null;
         }
         public void Execute(object parameter)
         {
            _window.Entities.Remove(_window.SelectedEntity);
            _window.SelectedEntity = null;
            _window.PropertyChanged?.Invoke(_window, new PropertyChangedEventArgs("SelectedEntity"));
         }
      }
   }
}
Steps to reproduce
- First observe that the ComboBoxat the bottom of the page changes size as the size of it's selected value changes.
- Next add a new row to the DataGridor edit theComboBoxin one of the already present rows to select the"Postpone the text"option; notice how theComboBoxdoesn't change size to fit the larger text, leading to the text being clipped.
- Finally resize the window to a larger size with one of the rows having selected "Postpone the text", and notice how theComboBoxnow increases in width to accommodate the longer text without clipping.
Conclusion/Question
My question is how can I force the ComboBox controls to automatically accommodate the width of their selected item, and increase the width of the grid row if necessary to do so. I want it such that the selected text will never be clipped, even if this means modifying the width of particular columns in the DataGrid to accommodate.
 
     
     
     
    