1
votes

I am bit confused about layout of my custom datatemplate in a listbox. Problem is that each of the ListBoxItem doesn't occupy the full row width.

Here is the DataTemplate for the ListBox:

<Window x:Class="NewPropertyGrid.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:NewPropertyGrid"
        Title="MainWindow" Height="200" Width="300">
    <Window.Resources>
        <DataTemplate x:Key="PropertyListTemplate">
            <Grid Background="Yellow">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>

                <TextBlock Text="{Binding Path=PropType,Converter={local:PropTypeToString}}"
                                   Margin="1"
                                   VerticalAlignment="Center"
                                   Background="LightGray"
                                   Foreground="Black"
                                   />

                <TextBlock Grid.Column="1"
                                   Text="="
                                   Margin="1"
                                   Background="LightGray"
                                   Foreground="Black"
                                   />

                <ContentControl Grid.Column = "2"
                                Content = "{Binding Editor}"
                                HorizontalAlignment = "Stretch"
                                VerticalAlignment = "{Binding VerticalContentAlignment}"
                                />
            </Grid>
        </DataTemplate>
    </Window.Resources>

    <ListBox x:Name="lv" ItemTemplate="{StaticResource PropertyListTemplate}" Background="Green" />
</Window>

As you see, there are 3 columns in the Grid. The third one is supposed to be Editor (FrameworkElement), decided via code behind. Here is the class data structure which acts as the source of information:

namespace NewPropertyGrid {
    public enum PropType { Name, Age, Surname };

    public class PropItem {
        public PropType PropType { get; set; }

        object _Value = null;
        internal object Value {
            get {
                return _Value;
            }
            set {
                _Value = value;
                DetectEditor();
            }
        }

        public FrameworkElement Editor { get; set; }

        public void DetectEditor() {
            var t = Value.GetType();
            if (t == typeof(string)) {
                var txt = new TextBox();
                txt.Text = Value as string;
                Editor = txt;
            }
            else if (t.IsArray) {
                var cmb = new ComboBox();
                cmb.ItemsSource = (IEnumerable)Value;
                if (cmb.Items.Count > 0)
                    cmb.SelectedIndex = 0;
                Editor = cmb;
            }
        }
    }
}


Now, when I load data in the listbox,

namespace NewPropertyGrid {
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();

            Loaded += (s, e) => {
                var list = new List<PropItem>();
                list.Add(new PropItem() {
                PropType = global::NewPropertyGrid.PropType.Name,
                Value = "Tester"
                });
                list.Add(new PropItem() {
                PropType = global::NewPropertyGrid.PropType.Surname,
                Value = new string[] { "X", "Y", "Z" }
                });

                lv.ItemsSource = list;
            };
        }
    }
}

I see that the frameworkelement Editor doesn't use the full row width as dictated by the third column of the Grid.

This is how the row looks like (screenshot of Snoop). Notice that the textbox with text 'Tester' is not using the full width of the 3rd column. Snoop tells me that the ContentPresenter in ListBoxItem default template, is not using the full width, even though Bd border does (notice ActualWidth of Bd)! This is how the row looks like (screenshot of Snoop)

How can I change the DataTemplate so that the Editor uses the full column width?

Thanks much!

1

1 Answers

5
votes

Set HorizontalContentAlignment to Stretch for your ListBoxItem. It can be done in ItemContainerStyle.

<ListBox x:Name="lv" ItemTemplate="{StaticResource PropertyListTemplate}"
         Background="Green">
   <ListBox.ItemContainerStyle>
      <Style TargetType="ListBoxItem">
          <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
      </Style>
   </ListBox.ItemContainerStyle>
</ListBox>