How to align Text in DataTemplate choosen by a DataTemplateSelector? - c#

I am trying to align text in a DataTemplate of a ListBox depending on the choice of the DataTemplateSelector.
What I want is something like this:
And tried to use a DataTemplateSelector
<DataTemplate x:Key="RequestTemplate" DataType="local:Message">
<TextBlock Text="{Binding Text}" Background="LightGreen" TextAlignment="Left" TextWrapping="Wrap"/>
</DataTemplate>
<DataTemplate x:Key="ResponseTemplate" DataType="local:Message" >
<TextBlock Text="{Binding Text}" Background="Yellow" TextAlignment="Right" TextWrapping="Wrap"/>
</DataTemplate>
<local:MesssageDataTemplateSelector x:Key="MessageDataTemplateSelector"
ResponseTemplate="{StaticResource ResponseTemplate}"
RequestTemplate="{StaticResource RequestTemplate}" />
The ListBox itself:
<ListBox ItemTemplateSelector="{StaticResource MessageDataTemplateSelector}" ItemsSource="{Binding Messages}" />
The colors are applied the alignment is not.
I also tried HorizontalAlignment, also not working. How to accomplish the effect?

One solution is to change the ListBoxItem style so that its HorizontalContentAlignment is Stretch:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>

Related

Can't select items in ListBox when CanDrag=True

I'm having trouble enabling drag (as in drag&drop) in an UWP ListBox. The selection stops working when I do that.
I have an UWP ListBox that contains an ItemTemplate with a single TextBlock in it. Everything was fine with the selection of items until I enabled CanDrag (i.e. drag&drop) on the TextBlock in the ListItem. After this I can't select items in the ListBox any longer by clicking on the items in the list. I can change selection by moving the focus with the arrow keys but selection with mouse interaction is no longer possible. If I set CanDrag back to False, selection starts working again.
Am I doing something wrong?
<ScrollViewer Grid.Column="0" HorizontalScrollMode="Disabled" VerticalScrollMode="Auto">
<ListBox x:Name="addProcessorListBox" ItemsSource="{Binding ProcessorTypes}"
SelectionMode="Single" DoubleTapped="OnDoubleTapped">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Padding" Value="0" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Margin="8,2,10,2" Text="{Binding Key}" FontSize="15" FontWeight="Bold"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate x:DataType="models:ProcessorType">
<TextBlock Grid.Column="0" Margin="18,8,10,8" Text="{Binding DisplayName}" FontSize="15" CanDrag="True" DragStarting="Processor_DragStarting"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
I tried changing the ListBox to a ListView, but the same behavior persists, i.e. selection does not work when clicking on the text.
I can reproduce this issue. I've reported it to the relevant team. They're investigating this issue.
As a workaround, you could use ListView control, but you do not need to drag the TextBlock in its ItemTemplate. You could choose to drag the whole ListViewItem by setting CanDragItems="True" and handling the DragItemsStarting event.
<ListView x:Name="addProcessorListBox" ItemsSource="{Binding ProcessorTypes}"
SelectionMode="Single" DoubleTapped="AddProcessorListBox_DoubleTapped" CanDragItems="True" DragItemsStarting="AddProcessorListBox_DragItemsStarting">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Padding" Value="0" />
</Style>
</ListView.ItemContainerStyle>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Margin="8,2,10,2" Text="{Binding Key}" FontSize="15" FontWeight="Bold" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Grid.Column="0" Margin="18,8,10,8" Text="{Binding DisplayName}" FontSize="15" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
We have confirmed that the best approach is ListView as we have it implemented in our github sample here
Actually the problem isn't quite related to ListBox/ListView but with
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
The following doc mentions that Stretch will stretches the child element to fill the allocated space of the parent element. But in this case, what is the size of parent space? Selection won't fail if specified Left/Right/Center but only with Stretch.
So actually this is a coding issue and you will need the property to set the size of parament element.

WPF how to put separator below each item in horizontal stackpanel

I've got a horizontal stackpanel on which I add items. I would like to add a separator below each project name, rather than it being to the right of the name, and that separator should span the whole page. These 2 questions haven't helped me up to now: How to add a vertical Separator? How can a separator be added between items in an ItemsControl
The View code is:
<ListView ItemsSource="{Binding Projects}" Margin="49,188,54,0">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="EventSetter_OnHandler"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ContentControl Content="{StaticResource Appbar_Suitcase}"/>
<Label Content="{Binding Name}"/>
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
make the first stackpanel vertical and put the content control and the label inside of a horizontal stackpanel. something like this:
<StackPanel>
<StackPanel Orientation="Horizontal">
<ContentControl Content="{StaticResource Appbar_Suitcase}" />
<Label Content="{Binding Name}"/>
</StackPanel>
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
</StackPanel>

Setting tag of a ListViewItem when used with Data Template

I have a List View
<ListView ItemsSource="{Binding Apparatus.AcidBaseApparatus}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Tag="{Binding AppratusName}">
<TextBlock Text="{Binding AppratusName}" Background="Azure">
</TextBlock>
<Image HorizontalAlignment="Center" MaxHeight="50" Source="{Binding ImageSource}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
<i:Interaction.Behaviors>
<behave:ApparatusDragBehavior></behave:ApparatusDragBehavior>
</i:Interaction.Behaviors>
</ListView>
I want to Bind the tag of each ListViewItem to ApparatusName as I have done with the StackPanel in the Data Template. I couldn't find any option fiddling with template on my own. Is it possible to do so?
You need to set the Binding in ItemContainerStyle (targeting ListViewItem):
<ListView ItemsSource="{Binding Apparatus.AcidBaseApparatus}">
<!-- ... -->
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Tag" Value="{Binding AppratusName}"/>
</Style>
</ListView.ItemContainerStyle>
<!-- ... -->
</ListView>

PivotItems do not resize after binding

I am binding a PivotItems but somehow the items are not resized properly, according to my margin declaration. Why is that?
EDIT: here is my new code and it still has gaps..
<Pivot x:Name="TpsSegmentsPivot" Title="Locator" Foreground="#FF888888" Style="{StaticResource PivotStyle1}" SelectionChanged="Pivot_SelectionChanged" Margin="0" Grid.Row="1" ItemTemplate="{StaticResource TpTemplate}" ItemsSource="{Binding DataSource}">
<Pivot.HeaderTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding id}" Margin="0, 16, 0, 0" Foreground="#FF888888" FontSize="32" FontFamily="Segoe WP" FontWeight="Light"/>
</Grid>
</DataTemplate>
</Pivot.HeaderTemplate>
</Pivot>
This is the template:
<DataTemplate x:Key="TpTemplate">
<ListBox Background="Black"
ItemsSource="{Binding Seg}"
ItemTemplate="{StaticResource SectionUCTemplate}"
HorizontalAlignment="Stretch"
VerticalAlignment="Top">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</DataTemplate>
Here is a screenshot with the red pivotItem..
I think the issue with the extra space is the Piviot Item you are using inside the DataTemplate tag. remove it and bind the header to a header template. I've used data binding on Pivots before and never seen this issue.
From one of my released apps:
<controls:Pivot Title="CAMPING CHECKLIST" ItemsSource="{Binding FilteredCategories}" Name="MainPivot">
<controls:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</controls:Pivot.HeaderTemplate>
<controls:Pivot.ItemTemplate>
<DataTemplate>
<!-- Your pivot item content here -->
</DataTemplate>
</controls:Pivot.ItemTemplate>
</controls:Pivot>
I believe the PivotItem in a PivotItem is the root of your issue.
your code should look similar to:
<controls:Pivot ItemsSource="{Binding tripTypeViewModel.TripTypeViewModelDataSource}" x:Name="TripsSegmentsPivot" Title=" " Foreground="#FF888888" Style="{StaticResource PivotStyle1}" SelectionChanged="Pivot_SelectionChanged" Grid.Row="1">
<controls:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding DataContext.tripTypeViewModel.HeaderText, ElementName=TripsSegmentsPivot}" Margin="0, 16, 0, 0" Foreground="#FF888888" FontSize="32" FontFamily="Segoe WP" FontWeight="Light"/>
</DataTemplate>
</controls:Pivot.HeaderTemplate>
<controls:Pivot.ItemTemplate>
<DataTemplate>
<ListBox x:Name="ItemsLB" ItemsSource="{Binding DataContext.tripTypeViewModel.Segment, ElementName=TripsSegmentsPivot}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Transparent">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<local:SectionUC HorizontalAlignment="Stretch" Grid.Row="1" VerticalAlignment="Top"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</controls:Pivot.ItemTemplate>
</controls:Pivot>
The first image is how I describe it, the second is how you currently have it :
This is the standard behaviour for PivotItems since they are always displayed with a margin. You should set a negative margin:
margin="-20,0,-20,0"

ToggleButton Checked Event Handling

I have ToggleButtons that are dynamically created based on my datasource. I would like to have only one togglebutton checked at a time when a user clicks one. How can I accomplish this?
<UserControl.Resources>
<ItemsPanelTemplate x:Key="HorizontalMiniDrawerList">
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
<DataTemplate x:Key="MiniDrawerRowTemplate">
<ToggleButton x:Name="_MiniDrawerButton" Width="60" Height="85" Style="{DynamicResource MiniDrawerButtonWhite}" Checked="_MiniDrawerButton_Checked" >
</ToggleButton>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Width}" Value="3">
<Setter TargetName="_MiniDrawerButton" Property="Width" Value="185"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<DataTemplate x:Key="MiniDrawerListItemTemplate">
<ListBox SelectionMode="Multiple" Background="#00000000" BorderThickness="0" Width="500"
ItemsPanel="{StaticResource HorizontalMiniDrawerList}"
ItemTemplate="{StaticResource MiniDrawerRowTemplate}"
ItemsSource="{Binding Row}" >
</ListBox>
</DataTemplate>
</UserControl.Resources>
<Grid Background="{DynamicResource ListBackgroundColor}" >
<ListBox x:Name="_MiniDrawerRows" BorderThickness="0" Background="Transparent" Margin="107,84,225,217" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Path=MiniDrawerRows, diagnostics:PresentationTraceSources.TraceLevel=High}"
ItemTemplate="{StaticResource MiniDrawerListItemTemplate}" >
</ListBox>
</Grid>
Update: Instead of using a togglebutton I used a radiobutton and changed the style of the radio button to look like a togglebutton.
<Style x:Key="MiniDrawerButtonWhiteRadioToToggleButton" BasedOn="{StaticResource {x:Type ToggleButton}}" TargetType="{x:Type RadioButton}">
I assume you mean "only one" instead of "only when". In that case you can use RadioButton (which is derived from ToggleButton) instead and set a GroupName on _MiniDrawerButton in your ItemTemplate. It looks like you are probably already using a custom ControlTemplate so you can use the same one for RadioButton by just changing the Style and ControlTemplate TargetTypes.

Categories