WPF TreeView ItemTemplate alighments - wpf

i have create my own tree-view with multi column Headers using standard wpf controls
Dock Panel
DataGrid , Just for creating the columns and having sorting and resizing capabilities. The height of datagrid is only 25 , we only need to show columns not data here.
The TreeView Control with hierarchy
i have add the image just to understand the problem and the XAML code
The Account Type should be always align at the left no matter how many levels are expanded in the "first column"
somewhere in the xaml of the TreeViewItemTemplate i lost the idea.. Can anyone help me to fix the alignments
<DockPanel DataContext="{StaticResource cust}">
<Button Command="{Binding rld}" Content="reload" DockPanel.Dock="Top"/>
<!--Unbound DataGrid just to display the headers-->
<DataGrid Height="25" DockPanel.Dock="Top" ItemsSource="{Binding Customers}" AutoGenerateColumns="False" Margin="0,0,0,0">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" Header="Name" x:Name="col0"></DataGridTextColumn>
<DataGridTextColumn Binding="{Binding AccountType}" Header="Account Type" x:Name="col1"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<!--Actual Binding with Tree View and item Template to display the properties-->
<TreeView ItemsSource="{Binding Customers}" DockPanel.Dock="Top">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding rel}">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding ElementName=col0,Path=ActualWidth}"></ColumnDefinition>
<ColumnDefinition Width="{Binding ElementName=col1,Path=ActualWidth}" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Name}" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding AccountType}" VerticalAlignment="Center" />
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</DockPanel>

The TreeView naturally indents child items, so its normal what you see.
A possible fix could be to set a negative left margin in the AccountType TextBlock with the same value of the indent, therefore neutralizing the gap.
You need to apply it only if its parent is expanded. This can easily be done modifying a bit your viewmodels.
<TextBlock Grid.Column="1" Margin="{Binding marginPropertyInVM}" Text="{Binding AccountType}" VerticalAlignment="Center"/>

You can limit the size of your first column by changing your template grids column definition to:
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="{Binding ElementName=col1,Path=ActualWidth}" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Name}" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding AccountType}" VerticalAlignment="Center" />
</Grid>
This way the first column will only be allowed the remaining width once the 2nd column and indent have been allocated their space.

Related

WPF ListView Stretch Width To Grid Column

I have a grid with two columns each with a width of 1* to be of equal widths. Inside the left-most column, I have a listview but for some reason I can't get the width to automatically stretch to the width of the grid column. I've tried all kinds of things like HorizontalContentAlignment="Stretch" and ScrollViewer.HorizontalScrollBarVisibility="Disabled" both of which were suggested as possible fixes to this issue... but they don't seem to address my issue. Here's my code:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListView ItemsSource="{Binding Path= Loads}" Grid.Column="0" MinHeight="20" MaxHeight="100" HorizontalAlignment="Left" HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Margin="6,-3,0,0" SelectedItem="{Binding Path= CurrentLoad}">
<ListView.ItemTemplate>
<DataTemplate DataType="local:Loads">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
<Button Width="26" Height="26">
<StackPanel>
<Image Source="{Binding Path=Icon}" Width="24" Height="24" Stretch="Fill"></Image>
</StackPanel>
</Button>
<TextBlock Text="{Binding Path=Name}" FontSize="9" Margin="3,6,3,3"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel Margin="0,-2,6,0" Grid.Column="1"></StackPanel>
</Grid
<ListView HorizontalAlignment="Left"
Well, there's your problem.

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:

XAML Datagrid columns width Issue

I have WPF datagrid. I want to use
i) maximum available width for "Description" textblock (present inside 1st column)
ii) Auto width for Image control (present inside 1st column) and
iii) "Auto" width for rest of the column.
I have written follwing xaml code. But width is not working as per requriement.
Edit
Issue : Instead, 2nd column text is getting truncated.
screenshot:
Any suggestions?
Thanks!
<Grid Margin="10,0,10,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<DataGrid Grid.Row="0" Grid.ColumnSpan="2" ItemsSource="{Binding SelectedItemsCollectionView}" HorizontalAlignment="Stretch" AutoGenerateColumns="False">
<DataGrid.Columns>
<!--Get maixmum available space for 1st Column-->
<DataGridTemplateColumn Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid Margin="5,0,0,0">
<Grid.ColumnDefinitions>
<!--Get "Auto" space for Image control-->
<ColumnDefinition Width="Auto" />
<!--Get remaining available space for Description textblock-->
<ColumnDefinition Width="*" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Stretch="None" Margin="0,0,5,0" Source="{Binding Converter={StaticResource ShowHideToImageConverterRef}, Path=IsHidden}"
Visibility="{Binding Converter={StaticResource VisibilityConverterRef}, Path=RowType}" HorizontalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding Description}" VerticalAlignment="Center" HorizontalAlignment="Left" />
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!--Get "Auto" space for 2nd Column-->
<DataGridTextColumn Binding="{Binding Comments}" Width="Auto" />
</DataGrid.Columns>
</DataGrid>
<Label Grid.Row="1" Grid.Column="0" Content="Name" ></Label>
<TextBox Grid.Row="1" Grid.Column="1" Margin="10,0,0,0" Text="{Binding EmpName}"/>
</Grid>
Issue resolved after applying below solution suggested by Scott on other stackoverflow post "DataGrid column width doesn't auto-update".
1) In your DataGridTextColumn Bindings (all except your * sized column) set NotifyTargetUpdated=True.
2) On your DataGrid, add a handler to the TargetUpdated event.
3) In your TargetUpdated event handler:
-- a) Set the DataGrid's * sized column's width to 0.
-- b) Call the UpdateLayout() method on the DataGrid.
-- c) Set the DataGrid's * sized column's width back to new DataGridLength(1, DataGridLengthUnitType.Star)

How do I get a DataGrid to fill a TabItem

I have the following layout
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="10">
...
</StackPanel>
<TabControl>
<TabItem Header="Summary">
<DataGrid ItemsSource="{Binding SummaryData}"
CanUserAddRows="False"
CanUserDeleteRows="False"
IsReadOnly="True"
HeadersVisibility="Column"
CanUserSortColumns="False" />
</TabItem>
...
</TabControl>
</DockPanel>
Without the DataGrid, the TabControl and TabItems fill the rest of the container perfectly, but when I add the DataGrid it stretches everything out to display all of the rows and columns.
EDIT: more clarity
I am looking to have the DataGrid stretch veritcally and horizontally to fill the TabItem. If it needs more space, I'd like to have the DataGrid's scrollbars appear.
I got the following to do what I want.
<TabItem Header="Summary" >
<Grid x:Name="SummaryGrid">
<DataGrid Height="{Binding ElementName=SummaryGrid, Path=ActualHeight}"
ItemsSource="{Binding SummaryData}"
CanUserAddRows="False"
CanUserDeleteRows="False"
IsReadOnly="True"
HeadersVisibility="Column"
CanUserSortColumns="False" />
</Grid>
</TabItem>
It works until I change the size of the parent panel. The ActualHeight isn't updated. It is good enough for now though.
Is it the kind of behavior you are looking for ?
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="10">
<TextBox Text="tttt" />
</StackPanel>
<TabControl VerticalAlignment="Top" HorizontalAlignment="Left">
<TabItem Header="Summary">
<DataGrid CanUserAddRows="False"
CanUserDeleteRows="False"
IsReadOnly="True"
HeadersVisibility="Column"
CanUserSortColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Column 1" Binding="{Binding}"></DataGridTextColumn>
</DataGrid.Columns>
<sys:String>Entry</sys:String>
</DataGrid>
</TabItem>
</TabControl>
</DockPanel>
By setting those alignments you will have the DataGrid stretch to the available space in the TabItem. but I'm not sure that's exactly waht you are looking for.
You can play with VerticalAlignment and HorizontalAlignment to get exactly what you need. (setting it to Top/Left/Stretch to get only TabItem, or DataGrid or both stretch the way you want)
The accepted answer is a work around...
The tab control will expand within its container along with any tab items. By making a grid its container and specifying row/column to be * sized (expanding within window) that will trickle down to datagrid.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="15"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
<RowDefinition Height="*"/>
<RowDefinition Height="10"/>
<RowDefinition Height="100"/>
<RowDefinition Height="15"/>
</Grid.RowDefinitions>
<TabControl Name="tabOperations"
Grid.Row="1"
Grid.Column="1"
TabStripPlacement="Top"
Margin="0,0,0,4"
>
<TabItem Header="Provider Accounts" >
<DataGrid AutoGenerateColumns="True"
IsReadOnly="True"
ItemsSource="{Binding ProviderAccounts}"/>
</TabItem>
</TabControl>
<GridSplitter Grid.Row="2"
Height="3"
Grid.Column="1"
HorizontalAlignment="Stretch" />
<TextBox Grid.Row="3" Grid.Column="1"
TextWrapping="Wrap" Text="{Binding Status}"
Margin="0,4,0,0"
/>
So regardless of size of the main window, it spans.

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 ?

Resources