SUMMARY
To make it clearer for future readers, here is a summary of the problem and its fix.
My grid sits in a page, that is used as the content for a tabitem. At runtime, the grid refused to fill the entire tabitem area, as seen in the screenshots below.
The problem was that the style for the tabitem contained a content template that displayed the page through a contentpresenter, inside a horizontal stackpanel. The stackpanel was overriding the stretch properties of the grid in the page.
The solution was to replace the stackpanel in the style with a grid. No more layout problems.
ORIGINAL QUESTION
I've got a StackPanel with a label and textbox inside a Grid, and I want to bind the width of the textbox to the width of the first two columns in the grid. I've generally been using the approach of binding the textbox width to its parent, and trying to bind that value to something that has the correct value, but I have tried direct binding as well, and no luck.
Here is my xaml:
<Page x:Class="BPC.CPI.Pages.CustomerMaintenance"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:cpihelpers="clr-namespace:BPC.CPI.ControlHelpers"
xmlns:robertData="clr-namespace:BPC.Robert.DataEncapsulation;assembly=BPC.Robert"
xmlns:robertGlobals="clr-namespace:BPC.Robert.Globals;assembly=BPC.Robert"
xmlns:avalon="clr-namespace:AvalonLambdas;assembly=AvalonLambdas"
xmlns:converters="clr-namespace:BPC.Utilities.ValueConverters;assembly=BPCUtilities"
mc:Ignorable="d"
d:DesignHeight="602" d:DesignWidth="1149"
Title="CustomerMaintenance" Name="ThisPage"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Page.Resources>
<converters:IntegerToBooleanConverter x:Key="IntegerToBooleanConverter"></converters:IntegerToBooleanConverter>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<ComboBox ItemsSource="{Binding PageModel.PageUser.AssociatedCustomers}" Name="CbCustomerName"
SelectedItem="{Binding PageModel.PageCustomer}"
Style="{StaticResource HeadingTwoComboBox}" cpihelpers:ComboBoxHelper.MaxDropDownItems="10">
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="LayoutTransform" Value="{StaticResource Transform.5x}"></Setter>
<Setter Property="Foreground" Value="Black"></Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
</Grid>
<Grid Name="GridMainContent" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="20"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid Name="GridGeneralCustomerInfo" Grid.Column="0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="5"></RowDefinition>
<RowDefinition Height=".35*"></RowDefinition>
<RowDefinition Height="1*"></RowDefinition>
<RowDefinition Height=".8*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Name="SpCustomerNotes" Orientation="Vertical" Grid.Column="0" Grid.Row="1"
HorizontalAlignment="Left">
<Label Name="LblCustomerNotes" Target="{Binding ElementName=TxtCustomerNotes}" Style="{StaticResource PromptText}" Content="{Binding Path=Text, ElementName=CbCustomerName}" ContentStringFormat="What is special about {0}?"></Label>
<TextBox Name="TxtCustomerNotes" AcceptsReturn="True" TextWrapping="Wrap" ScrollViewer.VerticalScrollBarVisibility="Auto"
MaxHeight="{Binding Path=ActualHeight, ElementName=SpCustomerNotes, Converter={avalon:LambdaValueConverter (param * 0.65)}}"
Text="{Binding PageModel.PageCustomer.CustomerInfo.CP_NOTES}"></TextBox>
</StackPanel>
<Grid Grid.Column="0" Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Style="{StaticResource HeadingFourBrown}" Grid.Column="0" Grid.ColumnSpan="2" Text="{Binding Path=Text, ElementName=CbCustomerName, StringFormat=A few questions about \{0\}...}"></TextBlock>
<StackPanel Name="SpReportingType" Orientation="Vertical" Grid.Row="1" Grid.Column="0" Margin="6,0,0,0">
<Label Name="LblReportingType" Target="{Binding ElementName=TxtReportingType}" Style="{StaticResource PromptText}" Content="Contractual or actual reporting?"></Label>
<ComboBox Name="CbReportingType" Style="{StaticResource ComboBoxWithoutBackground}" SelectedValuePath="REPORTING_TYPE_ID"
ItemsSource="{Binding PageModel.PageSelection.ReportingTypes}" DisplayMemberPath="NAME"
SelectedValue="{Binding PageModel.PageCustomer.CustomerInfo.REPORTING_TYPE_ID}"></ComboBox>
</StackPanel>
<StackPanel Name="SpReportingLevel" Orientation="Vertical" Grid.Row="2" Grid.Column="0" Margin="6,0,0,0">
<Label Name="LblReportingLevel" Target="{Binding ElementName=TxtReportingLevel}" Style="{StaticResource PromptText}" Content="How should we roll up data?"></Label>
<ComboBox Name="CbReportingLevel" Style="{StaticResource ComboBoxWithoutBackground}" SelectedValuePath="REPORTING_LEVEL_ID"
ItemsSource="{Binding PageModel.PageSelection.ReportingLevel}" DisplayMemberPath="NAME"
SelectedValue="{Binding PageModel.PageCustomer.CustomerInfo.REPORTING_LEVEL_ID}"></ComboBox>
</StackPanel>
<StackPanel Name="SpReportingPounds" Orientation="Vertical" Grid.Row="3" Grid.Column="0" Margin="6,0,0,0">
<Label Name="LblReportingPounds" Target="{Binding ElementName=TxtReportingPounds}" Style="{StaticResource PromptText}" Content="Net or gross weights?"></Label>
<ComboBox Name="CbReportingPounds" Style="{StaticResource ComboBoxWithoutBackground}" SelectedValuePath="REPORTING_LBS_ID"
ItemsSource="{Binding PageModel.PageSelection.ReportingPounds}" DisplayMemberPath="NAME"
SelectedValue="{Binding PageModel.PageCustomer.CustomerInfo.REPORTING_LBS_ID}"></ComboBox>
</StackPanel>
<StackPanel Name="SpInventoryLevel" Orientation="Vertical" Grid.Row="1" Grid.Column="1" Margin="6,0,0,0">
<Label Name="LblInventoryLevel" Target="{Binding ElementName=TxtInventoryLevel}" Style="{StaticResource PromptText}" Content="Customer or title?"></Label>
<ComboBox Name="CbInventoryLevel" Style="{StaticResource ComboBoxWithoutBackground}" SelectedValuePath="INV_RPT_LEVEL_ID"
ItemsSource="{Binding PageModel.PageSelection.InventoryReportingLevel}" DisplayMemberPath="NAME"
SelectedValue="{Binding PageModel.PageCustomer.CustomerInfo.INV_RPT_LEVEL_ID}"></ComboBox>
</StackPanel>
<StackPanel Name="SpReportByPO" Orientation="Vertical" Grid.Row="2" Grid.Column="1" Margin="6,0,0,0">
<Label Name="LblReportByPO" Target="{Binding ElementName=TxtReportByPO}" Style="{StaticResource PromptText}" Content="Do we report by PO?"></Label>
<CheckBox Name="ChkReportByPO" Style="{DynamicResource SliderCheckBox}" HorizontalAlignment="Left" Checked="ChkReportByPO_Checked"
IsChecked="{Binding PageModel.PageCustomer.CustomerInfo.IS_REPORTED_BY_PO, Converter={StaticResource IntegerToBooleanConverter}}"></CheckBox>
</StackPanel>
</Grid>
<Grid Name="GridMiscellaneous" Grid.Column="0" Grid.Row="3">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="5"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="5"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Style="{StaticResource HeadingFourBrown}" Grid.Row="0" Text="Other stuff"></TextBlock>
<StackPanel Name="SpSaveDirectory" Orientation="Vertical" Grid.Row="1" Margin="6,0,0,0">
<Label Name="LblSaveDirectory" Target="{Binding ElementName=TxtSaveDirectory}" Style="{StaticResource PromptText}" Content="Where should saved reports go?"></Label>
<TextBox Name="TxtSaveDirectory" ></TextBox>
</StackPanel>
<StackPanel Name="SpFrequency" Orientation="Vertical" Grid.Row="3" Margin="6,0,0,0">
<Label Name="LblFrequency" Target="{Binding ElementName=TxtFrequency}" Style="{StaticResource PromptText}" Content="{Binding Path=Text, ElementName=CbCustomerName}" ContentStringFormat="How often do you run reports for {0}?"></Label>
<TextBox Name="TxtFrequency" ></TextBox>
</StackPanel>
<StackPanel Name="SpHoursPerReport" Orientation="Vertical" Grid.Row="5" Margin="6,0,0,0">
<Label Name="LblHoursPerReport" Target="{Binding ElementName=TxtHoursPerReport}" Style="{StaticResource PromptText}" Content="How many hours do you spend per report (whole hours)?"></Label>
<TextBox Name="TxtHoursPerReport" ></TextBox>
</StackPanel>
</Grid>
</Grid>
<Grid Name="GridCustomerPeopleAndTitles" Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="1.2*"></RowDefinition>
<RowDefinition Height="1.5*"></RowDefinition>
<RowDefinition Height=".8*"></RowDefinition>
</Grid.RowDefinitions>
<Grid Name="GridCustomerPeople" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Name="TxtbCustomerPeople" Grid.Row="0" Style="{StaticResource HeadingFourBrown}" Text="{Binding Path=Text, ElementName=CbCustomerName, StringFormat=These people also work with \{0\}}"></TextBlock>
<StackPanel Orientation="Vertical" Grid.Row="1" Margin="6,0,0,0">
<Label Name="LblSalesReps" Style="{StaticResource PromptText}" Content="Sales Reps:"></Label>
<TextBlock Name="TxtbSalesReps" Text="{Binding PageModel.PageCustomer.SalesReps}" TextTrimming="CharacterEllipsis" MaxWidth="550"></TextBlock>
</StackPanel>
<StackPanel Orientation="Vertical" Grid.Row="2" Margin="6,0,0,0">
<Label Name="LblBillers" Style="{StaticResource PromptText}" Content="Billers:"></Label>
<TextBlock Name="TxtbBillers" Text="{Binding PageModel.PageCustomer.Billers}" TextTrimming="CharacterEllipsis" MaxWidth="550"></TextBlock>
</StackPanel>
<StackPanel Orientation="Vertical" Grid.Row="3" Margin="6,0,0,0" HorizontalAlignment="Stretch">
<Label Name="LblCams" Style="{StaticResource PromptText}" Content="Customer Account Managers:"></Label>
<TextBlock Name="TxtbCams" Text="{Binding PageModel.PageCustomer.CAMs}" TextTrimming="CharacterEllipsis"></TextBlock>
</StackPanel>
</Grid>
<Grid Name="GridTitleGroups" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Name="TxtbTitleGroups" Grid.Row="0" Style="{StaticResource HeadingFourBrown}" Text="{Binding Path=Text, ElementName=CbCustomerName, StringFormat=Group \{0\}\'s titles}"></TextBlock>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="15"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListBox Name="ListTitles" ItemsSource="{Binding}" Grid.Column="1" ToolTip="{Binding Source={x:Static robertGlobals:Messages.DragTitles}}">
</ListBox>
<Border Grid.Column="3" Style="{StaticResource BlueBorder}">
<Grid Name="GridTitleGroupItems" Grid.Column="3">
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Rectangle Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Fill="{StaticResource BrownAccentBrush}" OpacityMask="{StaticResource StrongOpacityMaskBrush}"
ToolTip="{Binding Source={x:Static robertGlobals:Messages.DragTitlesNew}}"></Rectangle>
<TextBlock Name="TxtbNewTitleGroup" Grid.Row="0" Text="Create a New Group" AllowDrop="True" HorizontalAlignment="Center"
VerticalAlignment="Center" Style="{StaticResource GreenAccentText}" ToolTip="{Binding Source={x:Static robertGlobals:Messages.DragTitlesNew}}"></TextBlock>
<TreeView Name="TreeTitleGroups" ItemsSource="{Binding}" AllowDrop="True" Grid.Row="1" BorderBrush="{x:Null}" ToolTip="{Binding Source={x:Static robertGlobals:Messages.DragTitles}}">
</TreeView>
</Grid>
</Border>
</Grid>
</Grid>
<Grid Name="GridCustomerGroups" Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Name="TxtbCustomerGroups" Grid.Row="0" Style="{StaticResource HeadingFourBrown}" Text="{Binding Path=Text, ElementName=CbCustomerName, StringFormat=Group \{0\}\'s customers}"></TextBlock>
</Grid>
</Grid>
</Grid>
</Grid>
</Page>
I've tried several recommended work-arounds from various questions and other sites, but nothing is working. I've tried sticking a border over cells I want to bind to and binding to its dimensions, using a label, nesting another grid, x:naming the ColumnDefinition and binding to the ActualWidth and more. Nothing. Works.
This seems like something that should be really simple in wpf, and I'm just missing come crucial, minor piece. I've wasted probably three hours on this. What am I doing wrong?
EDIT:
I just realized that it appears that I'm binding to the width of the entire GridMainContent - I'm not. That was just kind of dummy value that has been replaced with each different solution I've tried.
Here is an image of my issue. The contents should fill the entire tab. Note that the surrounding grid is sizing down to fit the content, rather than the content sizing up to fit the grid. I've defined implicit styles that set HorizontalAlignment=Stretch on every parent element for my content, but nothing appears to be working.
What I expect it to do, is for the left portion (with the dropdowns) and the right portion (with the sales reps & such) to be equal in width, filling the entire content area of the tab.