I'm confused with Grid layout in ListBoxItem of WPF - wpf

I'm newer in wpf,recently i have a requirement need to create an listbox and when i practice in DataTemplate ,the issue comed.my layout code like below
<ListBox HorizontalAlignment="Stretch" HorizontalContentAlignment="Left">
<ListBoxItem HorizontalAlignment="Stretch">
<Grid ShowGridLines="True" Height="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Row="0" Grid.ColumnSpan="2"
Width="200" Height="40" Fill="Gray"/>
</Grid>
</ListBoxItem>
</ListBox>
the begining,i set the width 100 on the first column,because the Rectange's width become to 200,so the first column width become more greater than 100,what happend when the grid to measue the child element?i am confused about it ,because i put the code in an commen state it run normally.any one tell me ,thanks

Related

Reproduce CSS property in StackPanels : Space Between

Is it possible in XAML to automatically separate elements in a StackPanel no matter what the size of the window is?
In CSS with the property : space between you can send elements to both sides of the parent. This is what I want to reproduce. Is it possible ?
A StackPanel does not work this way , see the documentation. It does not have a notion of the available space or remaining space to divide, it just stacks elements in one direction.
Arranges child elements into a single line that can be oriented horizontally or vertically.
What you can do instead is use a DockPanel. It allows stacking controls to either side of the panel and by default the last element added to it fills the remaining space. The Border here serves as a dummy element to take the remaining space. Usually, you would put a control there that is actually used. Please be aware that this example only reproduces what you explicitly asked for, the panel allows for much more complex layouts. See remarks from the documentation.
<DockPanel>
<Rectangle DockPanel.Dock="Left" Fill="Black" Width="100" Height="100"/>
<Rectangle DockPanel.Dock="Right" Fill="Black" Width="100" Height="100"/>
<Border/>
</DockPanel>
An alternative is to use a Grid with three columns, where the left and right columns use Auto as Width so the contained controls only take up as much space as they need, while the center column has its Width set to *, which will make it fit the remaining space.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Fill="Black" Width="100" Height="100"/>
<Rectangle Grid.Column="2" Fill="Black" Width="100" Height="100"/>
</Grid>
The relevant portion on size attributes for Grid:
Columns and rows that are defined within a Grid can take advantage of Star sizing to distribute remaining space proportionally. When Star is selected as the height or width of a row or column, that column or row receives a weighted proportion of the remaining available space. This is in contrast to Auto, which distributes space evenly based on the size of the content that is within a column or row.
Update for your list example. You can define a data template for the items.
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" Margin="25,60,25,25" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Border Padding="0,25" BorderThickness="0 0 0 1" BorderBrush="#3D3C44">
<Grid Width="378" Background="black">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="hello" Foreground="white"/>
<Border Grid.Column="1" x:Name="PlaceholderForYourContentAndBindings" Background="Red"/>
<theme:OnOff Grid.Column="2" Height="21" Width="38" HorizontalAlignment="Right" Grid.Column="1" Toggle="{Binding status , Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MouseLeftButtonDown="OnOff_MouseLeftButtonDown" />
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
If you want two fixed columns in the ListView, use a UniformGrid instead of a WrapPanel and remove the fixed sizes. With an ItemContainerStyle the items will then scale with the window.
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding StringItems}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="2" Margin="25,60,25,25" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Border Padding="0,25" BorderThickness="0 0 0 1" BorderBrush="#3D3C44">
<Grid Background="black">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="hello" Foreground="white"/>
<Border Grid.Column="1" x:Name="PlaceholderForYourContentAndBindings" Background="Red"/>
<theme:OnOff Grid.Column="2" Height="21" Width="38" HorizontalAlignment="Right" Grid.Column="1" Toggle="{Binding status , Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MouseLeftButtonDown="OnOff_MouseLeftButtonDown" />
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Width of Textbox, which placed in grid column, extends when inserting long text

When I put a Textbox in a grid column like below
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MinWidth="115"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="90"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="hello"/>
<TextBox Grid.Column="1" />
<Button Grid.Column="2" Content="push me"/>
</Grid>
</StackPanel>
I get proper result, i.e. textbox width is get from parent grid
But when I type a long text, the textbox starts exceeding its column and it stops extending after several extra letters
To .Net 4.6.2, I get same result but changing to .Net 4.7.2 the problem is solved i.e. the textbox width is not changing.
My software is compiled .Net 4.0, is there a solution to solve this for lower .net than 4.7.2?
Tried Pavel's first idea: removing stackpanel and adding another grid row in, still not working in .net 4.6.2
Tried Pavel's second idea: making the width of first column "Auto" instead of "1*". This works, the textbox doesn't extend (.net 4.6.2), however I really wanted the first and second column be responsive to resize.
You can solve this be removing the StackPanel and adding RowDefinition to Grid. You can also set TextWrapping="Wrap" for TextBox for wrapping a long text
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="90"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Text="hello" MinWidth="115"/>
<TextBox Grid.Column="1" TextWrapping="Wrap"/>
<Button Grid.Column="2" Content="push me"/>
</Grid>
StackPanel Y dimension is constrained to content, it will be automatically expanded to its content, more details can be found at panels overview
To me this is a bug that Textbox text size can change its parent width (grid width). This is happening in VS2019 .Net 4->4.6.2 but not in and after .Net 4.7.2.
For anybody faces this problem, I found below workaround by defining an invisible grid which contains textblocks. I get the widths of columns and give them to controls placed in a StackPanel.
<some container>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" MinWidth="115"/>
<ColumnDefinition Width="3*" />
<ColumnDefinition MinWidth="90"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0"/>
</Grid.RowDefinitions>
<TextBlock x:Name="C0" Grid.Column="0" />
<TextBlock x:Name="C1" Grid.Column="1" Margin="5"/>
<TextBlock x:Name="C2" Grid.Column="2" />
</Grid>
<StackPanel Orientation="Horizontal">
<TextBlock Width="{Binding ElementName=C0, Path=ActualWidth }" Text="hello" />
<TextBox Width="{Binding ElementName=C1, Path=ActualWidth }" Margin="5" />
<Button Width="{Binding ElementName=C2, Path=ActualWidth }" Content="push me"/>
</StackPanel>
</some container>
The margin should be the same for column in grid and control in StackPanel (see second column).

How to create empty expanding grid col in expander header

I'm trying to create a custom expander header that will show one text box on the left, and several others on the right, and as the windows grows horizontally the left and right text blocks get further apart. It feels like this should work, but everything stays left justified.
<Expander.Header>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" Name="LeftJustifiedCol" ></ColumnDefinition>
<ColumnDefinition Width="*" Name="EmptySpaceCol" ></ColumnDefinition>
<ColumnDefinition Width="Auto" Name="RightJustifiedCol" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Margin="5,0,5,0" Text="{Binding GroupByValue}"></TextBlock>
<DockPanel Grid.Column="2" HorizontalAlignment="Right">
<TextBlock DockPanel.Dock="Right" Margin="5,0,5,0" Text="Net: $0.00"></TextBlock>
<Button DockPanel.Dock="Right" Margin="5,0,5,0" Width="Auto" Name="DeleteEntityBtn" Click="DeleteEntityBtn_Click" >Del</Button>
</DockPanel>
</Grid>
</Expander.Header>
any suggestions?
I am guessing WPF isn't rendering the middle column because it contains no content, so it takes up no space in the UI. Perhaps a DockPanel with LastChildFill="False" would work better than a Grid

AutoSizing of Usercontrol

For a WPF application I have a user control MyUsrCntrl with Height=300 and Width=300
When i place MyUsrCntrl in a window and set its size to 600x600 the user control get resized but the controls in that does not get resized ,
is there any solution for this.
If you want to extend and compress the height and Width of your Usercontrol then make the Parent Controls Height="*" and Width="*" and don't assign any height and width to your controls present inside UserControl. Something like:
<Grid Margin="4" Background="Orange">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="It is fixed" Margin="1"/>
<Button Content="It is fixed"/>
</StackPanel>
<StackPanel Grid.Column="1">
<TextBlock Text="It is variable" Margin="1"/>
<Button Content="It is fixed" Margin="2"/>
</StackPanel>
</Grid>

3 Column ListBox in Silverlight for Wp7

I'm really going mad ... but the whole evening I'm trying to create a 3 column listbox. I want that the 3 columns are spread over the whole size of the listbox and not sticked together like they do when using the code below.
So, here's my XML
<ListBox Background="Red" HorizontalContentAlignment="Stretch"
ItemsSource="{Binding ListItems}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch" Background="Aquamarine">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="A"/>
<TextBlock Grid.Column="1" Text="B"/>
<TextBlock Grid.Column="2" Text="C"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Hope you can help me.
If you set the Width attribute of a ColumnDefinition to Auto that column will only use the minimum required width. Change the width of all 3 columns to *.
Also try setting the HorizontalAlignment attribute of the 3 TextBlocks to Center.
Right now I found a solution:
http://social.msdn.microsoft.com/Forums/en-US/windowsphone7series/thread/d93281f3-d369-45b9-ae50-ce273941f959

Resources