TextBox in UserControl doesn't take all the space - wpf

I have a WPF listbox with custom items. Each item is a user control consisting of a grid with two textboxes. I want that the right one takes all the space to fill the ListBoxItem. But all I get working is that the item itself takes the whole space but the textbox takes the size of its content.
So this is the listbox:
<ListBox x:Name="leftListBox" Grid.Column="0" Margin="10"
HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<local:CustomLine />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And the user control:
<UserControl x:Class="SharpComparer.CustomLine"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="30">
<UserControl.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBox x:Name="NumberColumn" x:FieldModifier="public"
Text="{Binding LineNumber}"
Grid.Column="0" HorizontalAlignment="Right" />
<TextBox x:Name="TextColumn" x:FieldModifier="public"
Text="{Binding Text}"
Grid.Column="1" HorizontalAlignment="Left" />
</Grid>
</UserControl>
What I have already tried after some research at some MSDN posts and around here on Stack Overflow: Setting the HorizontalContentAlignment to Stretch for Listbox.ItemContainerStyle. I used some borders to find the piece which makes problems. The ListBoxItems seem to take the whole width, the usercontrol and its grid, too. The textbox does not take all the space although I thought that Width="*" inside the grid's ColumnDefinition would do that.
Another idea was to bind the textbox width to its parent size, but then it also takes the space of the left textbox (which makes sense, because it gets the whole width) and subtracting this width doesn't seem to work.
What am I doing wrong?

You have to change your UserControl code from this:
<TextBox x:Name="TextColumn" x:FieldModifier="public"
Text="{Binding Text}"
Grid.Column="1" HorizontalAlignment="Left" />
to this:
<TextBox x:Name="TextColumn" x:FieldModifier="public"
Text="{Binding Text}"
Grid.Column="1" HorizontalAlignment="Stretch" />

Related

How can I make align all the textboxes align in same vertical position in wpf?

Hi i created lable's and text boxs in wpf but text boxes are started different position How can I make align all the textboxes align in same vertical position?
<DockPanel LastChildFill="True"
HorizontalAlignment="Stretch">
<Label DockPanel.Dock="Left"
Style="{DynamicResource EditorHLabelNoIdentStyle}" Content="{x:Static r:Resources.LABEL_POSITION}"/>
<TextBox ToolTip="{x:Static r:Resources.LABEL_POSITION_TIP}"
Style="{DynamicResource EditorTextBoxStyle}" Text="{Binding XPath=nameofthedataset, Mode=TwoWay}"/>
</DockPanel>
<DockPanel LastChildFill="True"
HorizontalAlignment="Stretch">
<Label DockPanel.Dock="Left"
Style="{DynamicResource EditorHLabelNoIdentStyle}" Content="{x:Static r:Resources.LABEL_POSITION}"/>
<TextBox ToolTip="{x:Static r:Resources.LABEL_POSITION_TIP}"
Style="{DynamicResource EditorTextBoxStyle}" Text="{Binding XPath=keywords, Mode=TwoWay}"/>
</DockPanel>
Use a Grid with two ColumnDefinitions and a RowDefinition for each row and then set the Grid.Row and Grid.Column attached properties
of each element to specify its position in the Grid:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label DockPanel.Dock="Left" Style="{DynamicResource EditorHLabelNoIdentStyle}" Content="{x:Static r:Resources.LABEL_POSITION}"/>
<TextBox Grid.Column="1" ToolTip="{x:Static r:Resources.LABEL_POSITION_TIP}" Style="{DynamicResource EditorTextBoxStyle}"
Text="{Binding XPath=nameofthedataset, Mode=TwoWay}"/>
<Label Grid.Row="1" DockPanel.Dock="Left" Style="{DynamicResource EditorHLabelNoIdentStyle}" Content="{x:Static r:Resources.LABEL_POSITION}"/>
<TextBox Grid.Row="1" Grid.Column="1" ToolTip="{x:Static r:Resources.LABEL_POSITION_TIP}"
Style="{DynamicResource EditorTextBoxStyle}" Text="{Binding XPath=keywords, Mode=TwoWay}"/>
</Grid>
With a number of rows, setting labels or texblocks and textboxes to row and column quickly gets a bit tedious.
You could instead use standard template to line things up in a stackpanel.
A headeredcontentcontrol has a template with a stackpanel to put a header above it's content. This xaml re-templates to use a grid with two columns. The size of the first is shared across the scope of it's containing stackpanel.
You can also avoid repeating all your standard styling and whatnot by applying it in the template.
My markup uses simplified example controls for clarity.
Your textboxes ( or whichever control you wanted to label ) complete with binding, tooltip etc go in the content of a headeredcontentcontrol. The label gets it's value from the header property.
The shared size scope and auto size on the column means all the instances end up with the maximum necessary width a label in that stackpanel requests. So the right column of controls (textboxes) lines up.
<StackPanel Grid.IsSharedSizeScope="True">
<StackPanel.Resources>
<Style TargetType="HeaderedContentControl">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="HeaderedContentControl">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="L" Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="{TemplateBinding Header}"
Margin="2,2,4,2"
/>
<ContentControl Content="{TemplateBinding Content}"
Grid.Column="1"
/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
<HeaderedContentControl Header="Label 1:">
<TextBox Text="Some textbox"/>
</HeaderedContentControl>
<HeaderedContentControl Header="A much longer label:">
<TextBox Text="A second textbox"/>
</HeaderedContentControl>
</StackPanel>

Fit a Textbox and a button in DataGrid Cell

I am trying to fit Textblock and a button in DataGrid Cell. The Textblock holds a portion of my text and when I click the button a dialog is display. I general my code looks like the one below
<DataGridTemplateColumn Header="Message" Width="Auto" MinWidth="60">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientetion="Horrizontal">
<TextBlock MinWidth="200" TextTrimming="CharacterEllipsis" Text="{Binding Text}" />
<Button DockPanel.Dock="Right" Width="90" Margin="1" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I want the Button to be always at righter side of the cell and its width to be fixed. The TextBlock needs to be variable, for example when I resize the window, and so the DataGrid, the TextBlock should stretch also.
The problem is that, I can not achieve this behaviour / view. The TextBlock varies on each DataGrid line and in some case the button is not at the righter of the cell.
I tried to change the StackPanel to Grid or DockPanel but still I can not get the desirable result.
Using Grid
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="100" Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" TextTrimming="CharacterEllipsis" Text="{Binding Text}" />
<Button Grid.Column="1" Margin="1" />
</Grid>
Any thoughts to share?
StackPanel doesn't really have the concept of aligning to the right. It stacks the elements as close as it can. You can get around this in different ways but in this case, use a DockPanel instead:
<DockPanel>
<Button DockPanel.Dock="Right" Width="90" Margin="1" />
<TextBlock MinWidth="200" TextTrimming="CharacterEllipsis" Text="{Binding Text}" />
</DockPanel>
Note that I moved the TextBlock to be the last child element of the DockPanel. DockPanel, after laying out the other child elements, allocates the remaining space to the last child element (unless you specify LastChildFill=false). In this case, we want the TextBlock to take up the remaining space.
UPDATE: based on the comments above, in addition to changing the panel type to a DockPanel (or Grid), you can use DataGridTemplateColumn.Width to a fixed value instead of Auto. This would make the column load with the specified with but the user can still modify the column with if they want to:
<DataGridTemplateColumn Header="Message" Width="60" MinWidth="60">
I'd set a static value to the DataGridTemplateColumn.Width--it can help with rendering performance. Set the size on your buttons too, so it doesn't size to fit text.
This works for me (I used the border for visualization purposes):
<Window ...
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type local:Model}"
x:Key="VmItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock Grid.Column="0" TextTrimming="CharacterEllipsis" Text="{Binding Original}" />
</Border>
<Button Grid.Column="1" Margin="1" Content="{Binding Encoded}" MinWidth="90" MaxWidth="90"/>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Message" CellTemplate="{StaticResource VmItem}" Width="300" MinWidth="100"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Proof:

WPF height and scroll at listbox - imposible

To keep things simple all i am trying to do is to place a listbox and a button below it. Although it seems simple it isn't. It is not, because it is in a GRID...
The row size is star size and listbox having verticalAlign top works great all the time. The problem is that I cannot add a button below it. Having a grid with 2 rows one star height and the other auto would place the button at the bottom of the form even if listbox contents are little. Trying to set both rows auto doesn't work when resizing as no scrollbar is visible at the listbox.... Any workaround for this??
Update some code
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DockPanel >
<ListBox DockPanel.Dock="Top" Name="lbStaff" ItemsSource="{Binding}"
Grid.Row="0" VerticalAlignment="Top" BorderThickness="0"
Background="WhiteSmoke" Margin="15,10,20,30" Style="{DynamicResource
ListBoxUsers}" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource
ListBoxTest1}"></Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel Margin="5,4,5,4">
<TextBlock HorizontalAlignment="Stretch" FontSize="16"><Run
Text="{Binding Name}"/> - <Run Text="{Binding Mode=OneWay,
Path=PositionString}"/></TextBlock>
<TextBlock >Τηλέφωνο <Run Text="{Binding Phone}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button DockPanel.Dock="Top" Grid.Row="0" HorizontalAlignment="Right"
VerticalAlignment="Top" Margin="0,10,7,0" Style="{DynamicResource
ButtonStyleNew1}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Image Source="/WpfApplication1;component/Images/filenew1.png"
Stretch="None" VerticalAlignment="Center"></Image>
<TextBlock Margin="5,0,0,0" FontSize="16">Προσθήκη Χρήστη</TextBlock>
</StackPanel>
</Button.Content>
</Button>
</DockPanel>
</Grid>
</Grid>
What i usually do is not using rows of grid but using DockPanel you can adjust the alignments by nesting each elements. But again it totally depends on the designer how they design that using grid row or any other way. What i got from the question the following code should help you out.
but if you post some code then we can figure out where the actual problem is.
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DockPanel>
<DockPanel DockPanel.Dock="Top">
<ListBox Height="50"/>
</DockPanel>
<DockPanel DockPanel.Dock="Bottom">
<Button Height="20" DockPanel.Dock="Top"/>
<Label/>
</DockPanel>
</DockPanel>
</Grid>
So your problem here is that you have the in the ListBox you have ScrollViewer.VerticalScrollbars=Visible that make it collapsed if you dont want scrollbars and i would suggest not to use margins more in the designing. if you still have scroll bars remove the height of the ListBox and make the window larger. It all depends upon the size of the window if you don't have the size and proper alignment. Refining your code
<Window xmlns:my="clr-
namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"
x:Class="MyLightWpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
xmlns:local="clr-namespace:MyLightWpfApplication.ViewModel"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<DockPanel >
<DockPanel DockPanel.Dock="Top" Width="400" Height="200">
<ScrollViewer DockPanel.Dock="Top" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<ListBox Name="lbStaff" ItemsSource="{Binding AutoCompleteData}"
BorderThickness="0"
Background="WhiteSmoke" >
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel >
<TextBlock HorizontalAlignment="Stretch" FontSize="16"><Run
Text="{Binding FirstName}"/> - <Run Text="{Binding Mode=OneWay,
Path=PositionString}"/></TextBlock>
<TextBlock >Τηλέφωνο <Run Text="{Binding LastName}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
</DockPanel>
<DockPanel DockPanel.Dock="Bottom">
<Button DockPanel.Dock="Top" Height="30" Grid.Row="0">
<Button.Content>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="16">Προσθήκη Χρήστη</TextBlock>
</StackPanel>
</Button.Content>
</Button>
<Label/>
</DockPanel>
</DockPanel>
</Grid>
</Window>
Its all dependent on how much data you have in the ListBox. I have tried this code populating listbox with 20 rows its not showing scrollbars at all
You might try auto for both and put a MaxHeight on the ListBox but you still take a chance of pushing the button off the screen. Or put both in a ScrollViewer. Or can you live with the button on top?
I solved this problem using a dockpanel. I docked buttons at bottom and then i let listbox to fill the remaining area..(lastchildfill=true) ...
It works fine...

Itemscontrol stretch silverlight

Inside my itemsControl the item are not occupying the whole width of the user control. Am using DataTemplateSelector (manually written class) for selecting the type of template.
I checked the post Silverlight: Set Items Widths in ItemsControl to Stretch but its not working for me. Items are not automatically stretching and utilizing the full space. Please help! Thanks in advance
<ItemsControl ItemsSource ="{Binding}" Margin="0,5,0,0" HorizontalContentAlignment="Stretch" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:AddressFieldsTemplateSelector Content="{Binding}" x:Name="addressTemplateSelectorObject">
<!-- TextBox template-->
<local:AddressFieldsTemplateSelector.TextBoxDataTemplate>
<DataTemplate>
<Grid Margin="0,0,0,5" HorizontalAlignment="Stretch" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width=".1*" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding AddressFieldName}" Grid.Column="0" Style="{StaticResource DefaultTheme_TextBlockStyle}"/>
<TextBox Text="{Binding AddressFieldValue, Mode=TwoWay}" Grid.Column="2" Style="{StaticResource TextBoxStyle}" TextWrapping="NoWrap" MaxLength="50" HorizontalAlignment="Stretch" />
</Grid>
</DataTemplate>
</local:AddressFieldsTemplateSelector.TextBoxDataTemplate>
</local:AddressFieldsTemplateSelector>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Items inside your datatemplate will always take up all available width due to the star width. The problem is most likely with the itemscontrol itself. Are you sure that the itemscontrol is not contained in a StackPanel, or auto-width Grid column. Is the HorizontalAlignment of the ItemsControl set to Left ?

What stops the tab?

I have the following xaml:
<ListBox ItemsSource="{Binding Path=ItemProperties.GeneralProperties}" Grid.Row="1"
Margin="0" Style="{StaticResource ListBoxStyle1}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="320" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" Grid.Column="0" />
<ContentPresenter Content="{Binding Converter={StaticResource PropertyInput}}" Grid.Column="1" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
where the ContentPresenter contains a TextBox, or a ComboBox, or a CheckBox.
To switch between the controls I need twice press the tab. Why???
I've already tried to comment the whole first column, without the TextBlock, unsuccessfully.
This worked for me for a DataGrid (which has a similar templating system).
<UserControl.Resources>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False"/>
</Style>
</UserControl.Resources>
Then anything which is a TabStop within the datagrid would work as a tabstop, but nothing else. Sorry I'm not sure what the equivalent code is for ListBox - but you may be able to figure it out from this.

Resources