Changing TextWrapping property of a TextBlock inside a GridView - xaml

I have a GridView with a TextBlock and a Button. For now, the MinWidth of the GridView's DataTemplate is fixed. The TextWrapping property of the TextBlock ss set to Wrap.
It looks like
the last DataTemplate has more text to show ( wrapping is ON ).
What I want to do is, if I tap on a text block and it has more text to show then it will expand ( in height ) to show the full text. For this, I thought to toggle its TextWrapping property on tap. But it doesn't seem to work this way.
Here's my XAML:
<GridView Name="TagsGridView"
ItemsSource="{x:Bind TagsList, Mode=OneWay}"
SelectionMode="None">
<GridView.ItemTemplate>
<DataTemplate x:DataType="x:String">
<Grid Background="#1A503E"
MinWidth="150">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{x:Bind}"
Grid.Column="0"
Height="Auto"
TextTrimming="CharacterEllipsis"
TextWrapping="Wrap"
VerticalAlignment="Center"
Foreground="White"
Padding="10"
Tapped="TextBlock_Tapped"/>
<Button Content=""
Name="btnTagDelete"
Click="btnTagDelete_Click"
Foreground="White"
Grid.Column="1"
Width="40"
Height="40"
FontFamily="Segoe MDL2 Assets"/>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
And here's my tapped event:
private void TextBlock_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
var textBlock = sender as TextBlock;
if (textBlock.TextWrapping == TextWrapping.Wrap) textBlock.TextWrapping = TextWrapping.NoWrap;
else textBlock.TextWrapping = TextWrapping.Wrap;
}
This causes the textblock to show some more text but doesn't change the height due to which all the text is not shown. I also tried to increase the height of TextBlock arbitrarily like this:
private void TextBlock_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
var textBlock = sender as TextBlock;
textBlock.Height = 1000;
}
Doing this does increase the height of the template by hardly 20 (unit) but then the Text inside the TextBlock becomes blank.
What is the correct way to achieve what I want?

Related

Is there a way to change the parent content for a popup in WinUI3?

In WinUI3 it seems that you are unable to modify the duration of a tooltip (similar to how WPF allowed a duration change with the ToolTipService.ShowDuration).
As such, I'm attempting to replicate the behavior using a Popup control such that the Popup will remain visible as long as the mouse is hovered over an element (utilizing the element's OnPointerEntered / OnPointerExited events to modify the IsOpen property of the Popup).
This displays the Popup correctly, however in my case the Popup exists inside a Grid which is inside the ListView.ItemTemplate for a ListView. ala:
<ListView>
<DataTemplate>
<Grid>
<TextBlock/>
<Popup/>
</Grid>
</DataTemplate>
</ListView>
Thus the popup only overlays the <Grid>, but still gets clipped within the region of the DataTemplate.
I'd like to have the popup overlay the <ListView> itself instead - is there a way to specify which content the popup will overlay such that it will overlay the <ListView>?
Or even better - to have it overlay all elements of the Window (replicating the placement of a tooltip?)
Is there a way to change the parent content for a popup in WinUI3?
Sure, you could place Popup at same level as ListView in current page. And listen ListView item PointerEntered and PointerExited event then pass current item datacontext to popup control.
Xaml
<ListView
Margin="0,10,0,45"
ItemsSource="{x:Bind Items}"
Visibility="Visible">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel
Orientation="Vertical"
PointerEntered="StackPanel_PointerEntered"
PointerExited="StackPanel_PointerExited">
<TextBlock x:Name="Id" Text="{Binding ID}" />
<TextBox
x:Name="FirstName"
GettingFocus="FirstName_GettingFocus"
Text="{Binding FirstName}" />
<TextBox x:Name="LastName" Text="{Binding LastName}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Popup
x:Name="PopupTip"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Popup.ChildTransitions>
<TransitionCollection>
<PaneThemeTransition Edge="Bottom" />
</TransitionCollection>
</Popup.ChildTransitions>
<StackPanel
Width="150"
Height="80"
Background="LightGray"
CornerRadius="4">
<TextBlock
x:Name="InfoLabel"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding ID}" />
</StackPanel>
</Popup>
Code behind
private void StackPanel_PointerEntered(object sender, PointerRoutedEventArgs e)
{
var ItemDataContext = (sender as FrameworkElement).DataContext;
PopupTip.DataContext = ItemDataContext;
PopupTip.IsOpen = true;
}
private void StackPanel_PointerExited(object sender, PointerRoutedEventArgs e)
{
PopupTip.DataContext = null;
PopupTip.IsOpen = false;
}

UWP Changing gridview element size programmatically

I'm trying to use XAML binding to affect the gridview datatemplate element size from a slider on my screen.
I have a gridview made of thumbnails images where the elements are defined as following:
<GridView.ItemTemplate >
<DataTemplate >
<StackPanel Orientation="Vertical"
HorizontalAlignment="Center"
VerticalAlignment="Center"
KeyDown="IsitenterThumb"
BorderBrush="LightSeaGreen"
BorderThickness="1"
PointerWheelChanged="ctlThumbnails_PointerWheelChanged">
<Image Source="{Binding thumb}"
x:Name="thumbimg"
Visibility="Visible"
Height="{Binding ItemSize}" Width="{Binding ItemSize, ElementName=page}" Stretch="Uniform"
Tapped="ThumbnailSelected"
DoubleTapped="CloseThumbnails"
/>
<TextBlock Text="{Binding name}" Margin="5,5"
Foreground="White"
Width="{Binding ItemSize}"
/>
</StackPanel>
</DataTemplate>
And I have the following variable defined as follow:
public double ItemSize
{
get => _itemSize;
set
{
if (_itemSize != value)
{
_itemSize = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ItemSize)));
}
}
}
private double _itemSize;
public event PropertyChangedEventHandler PropertyChanged;
I would have thought that changing the value of ItemSize would have affected the gridview datatemplate. This is taken litterally from the PhotoLab sample.
Instead I get a single huge "thumbimg" per page... Any help would be greatly appreciated!
Ok... I got it finally. I'm not quite sure what I was doing wrong above, but the code below works.
I have put the DataTemplate as part of a Page.Resource, I'm not sure if this is what was causing the binding issue. However the Xaml code looks like this:
<Page.Resources>
<DataTemplate x:Key="ThumbnailsTemplate">
<StackPanel Orientation="Vertical"
HorizontalAlignment="Center"
VerticalAlignment="Center"
KeyDown="IsitenterThumb"
BorderBrush="LightSeaGreen"
BorderThickness="1"
<Image Source="{Binding thumb}"
x:Name="thumbimg"
Visibility="Visible"
Height="{Binding ItemSize, ElementName=page}" Width="{Binding ItemSize, ElementName=page}"
Stretch="Uniform"
Tapped="ThumbnailSelected"
DoubleTapped="CloseThumbnails"
/>
<TextBlock Text="{Binding name}" Margin="5,5"
Foreground="White" Width="{Binding ItemSize}"
/>
</StackPanel>
</DataTemplate>
</Page.Resources>
<GridView x:Name = "ctlThumbnails" Grid.Column="0"
BorderBrush="White" BorderThickness="2"
Grid.RowSpan="4" Grid.Row="0" Grid.ColumnSpan="3" Height ="auto" Width="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Margin="30,30,30,30" KeyDown="IsitenterThumb"
DoubleTapped="CloseThumbnails"
ItemTemplate="{StaticResource ThumbnailsTemplate}">
</GridView>
And here is the C# code to affect the bound variable ItemSize
public event PropertyChangedEventHandler PropertyChanged;
public double ItemSize
{
get => _itemSize;
set
{
if (_itemSize != value)
{
_itemSize = value;
topcmdbarcontent.Text = "Thumb Size:" + _itemSize.ToString();
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ItemSize)));
}
}
}
private double _itemSize;
From this, when you change the value of ItemSize, through a ValueChanged event, for example, it does change the grid element size dynamically.

uwp FlipView Context Indicator as GridView is not recieving user interaction

I am using a GridView ( and I even tried ListView for this purpose ) as a context indicator of my FlipView. The Problem is that when I try to tap/click on a gridViewItem in order for it to get selected and hence changing the flipviewItem index as well, the gridview is not recieving any tap or click interaction by the user to change it. However when I change flipviewItem from directly flipview, it works as expected and gridview item selected is also changed accordingly.
CODE
<Grid>
<FlipView x:Name="MainFlipView" ItemsSource="{x:Bind MyItemsSource}" Visibility="Visible"
SelectionChanged="FlipChanged">
<FlipView.ItemTemplate>
<DataTemplate x:DataType="data:Video">
<userControls:FlipDataTemplate />
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
<GridView SelectionChanged="ContextChanged"
Name="ContextIndicator"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Margin="0,0,12,12"
ItemsSource="{x:Bind MyItemsSource}">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Video">
<Image Width="40" Height="40" Source="{x:Bind Display}"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
C#
private void FlipChanged(object sender, SelectionChangedEventArgs e)
{
ContextIndicator.SelectedIndex = MainFlipView.SelectedIndex;
}
private void ContextChanged(object sender, SelectionChangedEventArgs e)
{
MainFlipView.SelectedIndex = ContextIndicator.SelectedIndex;
}
You need to set IsItemClickEnabled to True on your GridView.
I was able to solve it with help of #JustinXL and I put FlipView and GridView in Rows and made RowSpan of FlipView to 2 so I got same UI as I wanted but now it works as expected, apparently if they are in same row then FlipView interferes with UI interaction on GridView.
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<FlipView x:Name="MainFlipView" ItemsSource="{x:Bind MyItemsSource}" Visibility="Visible" Grid.RowSpan="2"
SelectionChanged="FlipChanged">
<FlipView.ItemTemplate>
<DataTemplate x:DataType="data:Video">
<userControls:FlipDataTemplate />
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
<GridView SelectionChanged="ContextChanged" Grid.Row="1"
Name="ContextIndicator"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,12,8"
Canvas.ZIndex="1"
ItemsSource="{x:Bind MyItemsSource}">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Video">
<Image Width="40" Height="40" Source="{x:Bind Display}"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>

Capture Element not using room from parent control

I am trying to create a page with a capture element and a button overlaid on top to take the picture.
The problem I've got is, the capture element won't use up the whole screen. There are bars above and below.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<CaptureElement
Grid.Row="0"
x:Name="capPreview"
Stretch="Uniform"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Tapped="capPreview_Tapped"
/>
<Button Content="Submit"
HorizontalAlignment="Center"
Grid.Row="1"
x:Name="btnTakePicture"
Click="btnTakePicture_Click">
<Button.Background>
<SolidColorBrush Color="Black" Opacity="100"/>
</Button.Background>
<Button.BorderBrush>
<SolidColorBrush Color="White"/>
</Button.BorderBrush>
</Button>
</Grid>
Edit: I have since used the code behind to rotate the capture element, however; upon doing so, the element now just has a box all around it instead of top and bottom.
<CaptureElement
Grid.Row="0"
x:Name="capPreview"
Tapped="capPreview_Tapped"
/>
Short of hard coding the height and width values, I am out of ideas.
It deos use the whole screen, the issue is the orientation of the preview is different than the orientation of the screen.
MediaCapture has a method SetPreviewRotation to handle this issue.
It works for me :) Just grid and Strech, If you want to have focus just make transparent grid outside CaptureElement
<Grid>
<Grid Tapped="SetFocus">
<CaptureElement x:Name="CaptureElement" Stretch="UniformToFill"/>
</Grid>
<Grid VerticalAlignment="Bottom">
<Button x:Name="SaveButton" Foreground="Transparent" IsDoubleTapEnabled="False" Width="48" Height="48" Background="Transparent" BorderBrush="Transparent"
Click="OnSaveButtonClicked" HorizontalAlignment="Stretch" Margin="12,0">
</Button>
</Grid>
</Grid>
Try this one it will capture directly with the button click
private async void Button_Click_3(object sender, RoutedEventArgs e)
{
Uri u = new Uri("ms-data:///local");
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("Photo.jpg");
IRandomAccessStream st = await file.OpenAsync(FileAccessMode.Read);
BitmapImage image = new BitmapImage();
image.SetSource(st);
img.Source = image;
}
<CaptureElement Name="element" Height="600"/>
<StackPanel>
<Button Content="Capture Image" Click="Button_Click_3"/>
</StackPanel>
<Image Name="img" Margin="0,0,0,0"/>

Toggle Button inside a canvas

I have a canvas object in my xaml that has a togglebutton and two textblocks, like this.
<ListBox.ItemTemplate>
<DataTemplate >
<Canvas HorizontalAlignment="Right" VerticalAlignment="Top" Width="485"
Margin="-15,0,-15,80" Visibility="Visible"
MouseLeftButtonUp="MandantenStackPanel_MouseLeftButtonDown">
<ToggleButton Name="FavToggle" Checked="FavChecked" Unchecked="FavUnchecked"
Style="{StaticResource CustomToggleButtonStyle}"
Foreground ="White" BorderBrush="Red" HorizontalAlignment="Left"
Canvas.Left="0" Canvas.Top="0">
<ImageBrush ImageSource="/Icons/favs.png" Stretch="UniformToFill" >
</ImageBrush>
</ToggleButton>
<TextBlock Text="{Binding MandantenNummer}" FontSize="24"
TextWrapping="Wrap" Canvas.Left="90" Canvas.Top="20"/>
<TextBlock Text="{Binding MandantenBezeichnung}" FontSize="24"
TextWrapping="Wrap" Canvas.Left="90" Canvas.Top="50"/>
</Canvas>
</DataTemplate>
</ListBox.ItemTemplate>
In my .cs i am binding a collection item to that listbox that also has a boolean called isFavorite that i'd like to toggle with my togglebutton. How can i access the data context from the canvas from inside my toggle event handlers? I tried it like i did it like i do it when you click on the textbox:
private void FavChecked(object sender, EventArgs e)
{
ClassX x = (sender as Canvas).DataContext as Class x;
x.isFavorite = true;
}
but that of course doesn't work cause my sender is the togglebutton and not the canvas. Can i access the canvas from here?
The sender is ToggleButton and not Canvas because that is the control on which you attached that event handler.
Also, DataContext is set recursively so ToggleButton inherits the same data context the parent has.