TextTrimming property of TextBlock placed in TreeViewItem using GridSplitter - c#

My XAML is very simple:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBlock FontSize="55" HorizontalAlignment="Center"
VerticalAlignment="Center" TextWrapping="Wrap">Left side</TextBlock>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Center" />
<TreeView Grid.Column="2" ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
<TreeViewItem>
<TreeViewItem.Header>
<TextBlock Text="The full string"
TextTrimming="CharacterEllipsis"/>
</TreeViewItem.Header>
<TreeViewItem>
<TreeViewItem.Header>
<TextBlock Text="The full string"/>
</TreeViewItem.Header>
</TreeViewItem>
</TreeViewItem>
</TreeView>
<Border BorderBrush="Green" BorderThickness="5" CornerRadius="5" Grid.Column="3" />
</Grid>
What I have is:
and it is not correct for me:
And what behavior I want is:
How can I use TextTrimming property of TextBlock placed in TreeViewItem?

You need to modify the style of your TreeViewItem, because the content is not stretched.
See style example and problem explanation at
https://leecampbell.com/2009/01/14/horizontal-stretch-on-treeviewitems/
Just apply the style from the link to your TreeView
<TreeView>
<TreeView.Resources>
<!--paste the style from the link here-->
</TreeView.Resources>
Sorry for not posting the style, but i don't get the formatting done.

Related

C# WPF Unable to select row by clicking in first column

I am new into WPF and I have problem as I mentioned in title.
I'm using ListBox.
When I click into row in first column. I cannot select value.
It works when I click on border of row.
In second column I have no problems.
This is how looks ListBox and Grid. And now how it's look running.
XAML code below
<Grid Grid.ColumnSpan="2" Margin="24,45,375,124" Grid.RowSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="400"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox x:Name="ProductListView" Height="200" VerticalAlignment="Top" SelectionChanged="ListBox_SelectionChanged" AutomationProperties.IsColumnHeader="True" RenderTransformOrigin="0.508,0.5" Grid.ColumnSpan="2" Margin="2,0,-19,0">
<ListBox.GroupStyle>
<GroupStyle/>
<!--
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold" HorizontalAlignment="Center"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
-->
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="350" x:Name="Nazwa_Produktu" />
<ColumnDefinition Width="100" x:Name="Cena_w_zl" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding PricePerUnit, StringFormat=\{0\} zł}" Grid.Column="1" HorizontalAlignment="Right" />
<ScrollViewer VerticalScrollBarVisibility="Hidden"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
The hidden Scrollbar seems to be overlapping with your first column, making the items inside unselectable.
I tested with your provided code and removed:
<ScrollViewer VerticalScrollBarVisibility="Hidden" />
This solved the issue you have mentioned!
Is there a reason why the hidden scrollbar has to be there?

Making a portion of a TreeViewItem wrap

I have a TreeViewItem that has multiple parts in it -- an icon, a header, and a piece of data. I'm trying to get the last part to wrap without making everything wrap, and I'm having no luck. Here's an illustration of the problem:
I've tried a few things that I've found on Stack Overflow, with no luck. There were three suggestions I found:
Put the item in a grid with a column with bound to the TreeView's actual width. This is implemented in the XAML below, but doesn't seem to help.
Disable horizontal scrolling on the TreeView with ScrollViewer.HorizontalScrollBarVisibility = "Disabled", which I also implemented in the XAML below.
Wrap what I need in a WrapPanel. I tried this, but got poor results. When I wrapped the whole TreeViewItem in one, I got wrapping that was hard to control (the whole item wraps, so all parts wrapped and it looked awful). When I wrapped just the desired TextBlock in one, I got no results at all. So I took it out.
Here's the template I have for the TreeViewItem:
<DataTemplate x:Key="BasicPropertyTemplate" DataType="{x:Type json:JProperty}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding RelativeSource={RelativeSource AncestorType=TreeView}, Path=ActualWidth}" />
</Grid.ColumnDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="3" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="3" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="3" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border
Width="12"
Height="12"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="{Binding Converter={StaticResource TypeToColorConverter}, ConverterParameter='Interior'}"
BorderBrush="{Binding Converter={StaticResource TypeToColorConverter}}"
BorderThickness="1" />
<TextBlock Grid.Column="2" Text="{Binding Name, Mode=OneWay}" />
<TextBlock Grid.Column="4" Text=": " />
<TextBlock
Grid.Column="6"
Text="{Binding Value, Converter={StaticResource StringFormatConverter}, Mode=OneWay}"
TextWrapping="Wrap" />
</Grid>
</Grid>
</DataTemplate>
Here's an illustration of the layout, so you can see how the TreeViewItem is composed:
Essentially, the gray part is the icon, the green parts are just spacers between items, the blue parts are header and a colon (essentially irrelevant to what this question is about), and the red part is the actual content.
It's the red part I want to wrap.
Here's the TreeView definition:
<TreeView
x:Name="JsonRoot"
Grid.Column="0"
ItemTemplateSelector="{StaticResource TreeViewTemplateSelector}"
Loaded="JsonRoot_Loaded"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
VirtualizingStackPanel.IsVirtualizing="True" />
I feel like I'm doing something simple wrong, but I'm not sure what. Is there a way to accomplish this without just locking the TextBlock width to something arbitrary, like 200?
My investigation showed that TextBlock Wrap doesn't work with <ColumnDefinition Width="Auto"/>. So I changed last <ColumnDefinition Width="Auto"/> in DataTemplate to <ColumnDefinition Width="*"/>.
Unfortunately TreeViewItem (which is a default container for TreeView items) has <ColumnDefinition Width="Auto"/> in its Template and places our items there. I have tried to make a custom template with <ColumnDefinition Width="*"/> and it worked but code is really long. So I decided to compensate the effect by binding Grid width:
<DataTemplate x:Key="BasicPropertyTemplate" DataType="{x:Type json:JProperty}">
<Grid Width="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}, Path=ActualWidth}" >
<Grid Margin="0,0,20,0"> <!--right margin to compensate excessive width-->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="3" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="3" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="3" />
<ColumnDefinition Width="*"/> <!--was Auto-->
</Grid.ColumnDefinitions>
<Border
Width="12"
Height="12"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="{Binding Converter={StaticResource TypeToColorConverter}, ConverterParameter='Interior'}"
BorderBrush="{Binding Converter={StaticResource TypeToColorConverter}}"
BorderThickness="1" />
<TextBlock Grid.Column="2" Text="{Binding Name, Mode=OneWay}" />
<TextBlock Grid.Column="4" Text=": " />
<TextBlock
Grid.Column="6"
Text="{Binding Value, Converter={StaticResource StringFormatConverter}, Mode=OneWay}"
TextWrapping="Wrap" />
</Grid>
</Grid>
</DataTemplate>
ScrollViewer.HorizontalScrollBarVisibility="Disabled" is important element and should be set.
Try changing the grid in DataTemplate with a DockPanel:
<DataTemplate>
<DockPanel>
<Border Width="12"
Height="12"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="{Binding Converter={StaticResource TypeToColorConverter}, ConverterParameter='Interior'}"
BorderBrush="{Binding Converter={StaticResource TypeToColorConverter}}"
BorderThickness="1" />
<TextBlock Text="{Binding Name, Mode=OneWay}" />
<TextBlock Text=": " />
<TextBlock Text="{Binding Value, Converter={StaticResource StringFormatConverter}, Mode=OneWay}"
TextWrapping="Wrap" />
</DockPanel>
</DataTemplate>

LongListMultiSelector Data Template stretches outside screen width - windows phone 8

I've the following pivot control in my application
<phone:PivotItem Header="{Binding Path=LocalizedResources.requests_title, Source={StaticResource LocalizedStrings}}" >
<Grid Margin="0,-12,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" >
<TextBlock FontWeight="Bold"
TextDecorations="Underline"
VerticalAlignment="Top"
TextWrapping="NoWrap"
FontSize="{StaticResource PhoneFontSizeMediumLarge}"
Foreground="{StaticResource PhoneAccentBrush}"
toolkit:TurnstileFeatherEffect.FeatheringIndex="1"/>
<toolkit:PhoneTextBox AcceptsReturn="False"
TextWrapping="NoWrap"
Visibility="Collapsed"
TextChanged="SearchBox_TextChanged"
toolkit:TurnstileFeatherEffect.FeatheringIndex="1"/>
</StackPanel>
<toolkit:LongListMultiSelector Grid.Row="1"
ItemsSource="{Binding Details_OC}"
SelectionChanged="Requests_SelectionChanged"
toolkit:TurnstileFeatherEffect.FeatheringIndex="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="0,0,24,0">
<toolkit:LongListMultiSelector.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0.25" BorderBrush="{StaticResource PhoneAccentBrush}">
<Grid Background="{StaticResource TransparentBrush}" HorizontalAlignment="Stretch" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal"
Grid.Row="0"
Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Top" >
<TextBlock Text="#" FontSize="{StaticResource PhoneFontSizeLarge}" />
<TextBlock x:Name="ID"
Text="{Binding ID}"
FontSize="{StaticResource PhoneFontSizeLarge}"
TextWrapping="NoWrap"/>
</StackPanel>
<TextBlock x:Name="date"
Text="{Binding Path=TIME, Converter={StaticResource dateConverter}}"
Grid.Row="0"
Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Top"
FontSize="{StaticResource PhoneFontSizeSmall}"
TextWrapping="NoWrap"/>
</Grid>
</Border>
</DataTemplate>
</toolkit:LongListMultiSelector.ItemTemplate>
</toolkit:LongListMultiSelector>
</Grid>
</phone:PivotItem>
The result appears as follows
You can see that the date Textblock is not appearing fully. I couldn't find the reason for this unexpected behavior. Please help.
Thank you.
The problem appears to be in the sizing of your columns. See the following, inside the <toolkit:LongListMultiSelector.ItemTemplate>:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
In this case I would give the first column a static width and then the second can fill the remaining space. Like this:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
Alternatively you may wish to take a look into the ItemInfoTemplate property of the LongListMultiSelector.
It gives you the ability to display a second column at the far right which does not get squashed over by the checkboxes when they become active.
An example can be found here.

Use placeholders in controltemplate

I have a number of grids that have almost the same layout. This is an example
<Grid x:Name="OptionChangeUserState" Grid.Row="0" Style="{StaticResource MenuItemGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Style="{StaticResource MenuItemTextblockStyle}" Text="Status wijzigen" Margin="0"/>
<Image Grid.Column="1" Source="/UserControlSolution;component/Image/user.png" Margin="5" />
</Grid>
I want to turn this in a controltemplate like here :no template property on grid style in WPF?
But how can I change the Textblock text and Image source when I use a controltemplate ?
You can achieve this by creating the one model with Text and Source properties. Then depending on the different number of instance where you want to use this ControlTemplate you can set the model instance in the Tag of your Grid.
<local:MyModel x:Key="myModel1" Text="" Source=""/>
<ContentControl Tag="{StaticResource myModel1}" Template={StaticResource myTemplate}>
</ContentControl>
and in template
<ControlTemplate x:Key="myTemplate" TargetType="ContentControl">
<Grid x:Name="OptionChangeUserState" Grid.Row="0" Style="{StaticResource MenuItemGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Style="{StaticResource MenuItemTextblockStyle}" Text="{Binding Tag.Text, RelativeSource={RelativeSource TemplatedParent}}" Margin="0"/>
<Image Grid.Column="1" Source="{Binding Tag.Source, RelativeSource={RelativeSource TemplatedParent}}" Margin="5" />
</Grid>
</ControlTemplate>
As far as I am aware, you can only do this with a DataTemplate and only if each of your data bound classes had properties of the same name, in this case, TextValue and ImageSource. I don't think that you can get access to the data object directly from the ControlTemplate.
<DataTemplate>
<Grid x:Name="OptionChangeUserState" Grid.Row="0" Style="{StaticResource MenuItemGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Style="{StaticResource MenuItemTextblockStyle}" Text="{Binding TextValue}" Margin="0"/>
<Image Grid.Column="1" Source="{Binding ImageSource}" Margin="5" />
</Grid>
</DataTemplate>
You'd also need to use the ContentTemplate property instead.
<ContentControl Content="{Binding DataObject}"
ContentTemplate="{StaticResource Template}" />
This can be done with data-binding, but it would be preferable to use a property interface so that you can simply type something like:
<local:OptionControl Text="Status wijzigen" ImageSource="/UserControlSolution;component/Image/user.png" />
This way you don't need to have your UI labels and icons in a separate data layer.
This can be achieved by creating a control class which defines Dependency Properties, and using TemplateBindings to bind to them in the ControlTemplate.
It's possible that an existing control has appropriate properties that you can create a template for. This HeaderedContentControl template should work for you, although a custom control would be nicer:
<Style x:Key="HeaderedContentControlStyle" TargetType="HeaderedContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="HeaderedContentControl">
<Grid Style="{StaticResource MenuItemGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Style="{StaticResource MenuItemTextblockStyle}" Text="{TemplateBinding Header}" />
<Image Grid.Column="1" Source="{TemplateBinding Content}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Usage:
<HeaderedContentControl Name="OptionChangeUserState" Grid.Row="0"
Style="{StaticResource HeaderedContentControlStyle}"
Header="Status wijzigen">
<BitmapImage>/UserControlSolution;component/Image/user.png</BitmapImage>
</HeaderedContentControl>
Note that we need to wrap the image path in BitmapImage explicitly. This is because the HeaderedContentControl.Content property is not declared as an image type, so WPF will not automatically convert it.
Use DataTemplate with some sort of DTO, DictionaryEntry will do for two items.
<DataTemplate DataType="{x:Type Collections:DictionaryEntry}" x:Key="gridTemplate">
<Grid Style="{StaticResource MenuItemGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Style="{StaticResource MenuItemTextblockStyle}" Text="{Binding Key}" Margin="0"/>
<Image Grid.Column="1" Source="{Binding Value}" Margin="5" />
</Grid>
</DataTemplate>
Usage:
<ContentControl ContentTemplate="{StaticResource gridTemplate}">
<ContentControl.Content>
<Collections:DictionaryEntry Key="Status wijzigen" Value="/UserControlSolution;component/Image/user.png" />
</ContentControl.Content>

One ScrollViewer for two ListBox

I've got 2 listbox and one scrollviewer and I want the scrollviewer to scroll the two listbox together. But i don't know how to do.. Here's my xaml :
<ScrollViewer Grid.Row="1">
<Grid>
<ListBox Name="listboxRSSFeedItems" Width="240" Height="644" Margin="0,0,240,0">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock TextWrapping="Wrap" Text="{Binding Title}" Grid.Row="0" FontSize="24" HorizontalAlignment="Left" />
<HyperlinkButton Content="Link to details" NavigateUri="{Binding Link}" HorizontalAlignment="Left" Grid.Row="1" Margin="0,0,0,30" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox Name="listboxRSSFeedItems2" Width="240" Height="644" Margin="240,0,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock TextWrapping="Wrap" Text="{Binding Title}" Grid.Row="0" FontSize="24" HorizontalAlignment="Left" />
<HyperlinkButton Content="Link to details" NavigateUri="{Binding Link}" HorizontalAlignment="Left" Grid.Row="1" Margin="0,0,0,30" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</ScrollViewer>
Thanks a lot
Ok. I just tried to do one listbox with grid. it works fine, but how to choose which grid to add my item.
I used to add with "listboxRSSFeedItems.Items.Add(item)", but now, how can i choose the 2nd Column only.
<ScrollViewer Grid.Row="1">
<ListBox x:Name="listboxRSSFeedItems" Width="480" Height="680">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid x:Name="first" Grid.Column="0">
<TextBlock TextWrapping="Wrap" Text="{Binding Title}" />
<HyperlinkButton NavigateUri="{Binding URL}" TargetName="_blank"/>
</Grid>
<Grid x:Name="second" Grid.Column="1">
<TextBlock TextWrapping="Wrap" Text="{Binding Title}" />
<HyperlinkButton NavigateUri="{Binding URL}" TargetName="_blank" />
</Grid>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
Thanks again
You shouldn't set height of your listBoxes.
ps: Consider layout using columns
<ScrollViewer >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox x:Name="first" Grid.Column="0" />
<ListBox x:Name="second" Grid.Column="1" />
</Grid>
</ScrollViewer>
Set VerticalScrollBarVisibility to "Disabled" for listBoxes.
And it will be better using StackPanel for this puprose instead of Grid.

Categories