UWP XAML: Custom Brush to draw a progress bar as Grid background - c#

I have a Universal Windows App with a UI like this:
A vertical grid defining an number of rows
Each row is a horizontal grid with a number of columns
I'd like each row to have a progress bar in its background as shown in this mockup:
I tried using a ProgressBar control with the Grid.ColSpan property set, but the progress bar is drawn above the text and buttons so that won't work.
My next idea was to use a Rectangle with a percentage width, but I don't think it's possible to specify a relative width.
My current idea is to implement a custom Brush that I can then set as Background property for each horizontal Grid, but I could not figure out how to do custom drawing inside my Brush implementation.
Sample XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.Background>
<MyCustomBrush RelativeWidth="75%"/> ???
</Grid.Background>
<Button Content="{x:Bind ToggleSymbol, Mode=OneWay}" Grid.Column="0"></Button>
<Button Grid.Column="1" Content="Title"></Button>
<TextBlock Text="SubTitle" Margin="0,0,10,0" Grid.Column="3"></TextBlock>
<ProgressBar Visibility="Collapsed" Grid.Column="0" Grid.ColumnSpan="5" Value="75" Maximum="100" Background="Transparent" Foreground="Red"></ProgressBar>
</Grid>

Two solutions here: reorder your XAML and put your ProgressBar directly after your background definition and before your buttons. This will cause it to be drawn under the buttons (As XAML draws in the order it finds things in XAML files by default, so reordering the XAML results in things being drawn in different orders)
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.Background>
<MyCustomBrush RelativeWidth="75%"/> ???
</Grid.Background>
<ProgressBar Visibility="Collapsed" Grid.Column="0" Grid.ColumnSpan="5" Value="75" Maximum="100" Background="Transparent" Foreground="Red" />
<Button Content="{x:Bind ToggleSymbol, Mode=OneWay}" Grid.Column="0"></Button>
<Button Grid.Column="1" Content="Title"></Button>
<TextBlock Text="SubTitle" Margin="0,0,10,0" Grid.Column="3"></TextBlock>
</Grid>
Another solution is to set the Canvas.ZIndex attached property on the ProgressBar to -1.
<ProgressBar Canvas.ZIndex="-1" .... ></ProgressBar>
which will cause it to be drawn under the rest of the Grid's content, which be default will have a ZIndex of 0.

i don't know what you done , but what is the problem in getting this type of Design
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="100" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<ProgressBar BorderBrush="Transparent" BorderThickness="2" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" VerticalAlignment="Stretch" Background="Transparent" Foreground="LightCoral" Minimum="0" Maximum="10" Value="7" />
<TextBlock Grid.Column="0" Grid.Row="0" Text="▶ Title" VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="50"/>
<TextBlock Grid.Column="3" Grid.Row="0" Text="▶ SubTitle" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="50"/>
<ProgressBar BorderBrush="Transparent" BorderThickness="2" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" VerticalAlignment="Stretch" Background="Transparent" Foreground="LightCoral" Minimum="0" Maximum="10" Value="5" />
<TextBlock Grid.Column="0" Grid.Row="1" Text="▶ Title" VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="50"/>
<TextBlock Grid.Column="3" Grid.Row="1" Text="▶ SubTitle" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="50"/>
<ProgressBar BorderBrush="Transparent" BorderThickness="2" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" VerticalAlignment="Stretch" Background="Transparent" Foreground="LightCoral" Minimum="0" Maximum="10" Value="8" />
<TextBlock Grid.Column="0" Grid.Row="2" Text="▶ Title" VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="50"/>
<TextBlock Grid.Column="3" Grid.Row="2" Text="▶ SubTitle" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="50"/>
</Grid>

Related

Align TextBlock in Button / StackPanel correctly

I try to align the TextBlocks to the left.
The button should take the rest of the area (Up to the picture).
How can I do this?
This is a UWP / C# App.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid VerticalAlignment="Center" HorizontalAlignment="Left">
<Button Background="Transparent" HorizontalAlignment="Stretch">
<StackPanel HorizontalAlignment="Left">
<TextBlock x:Name="TextBlock1" TextWrapping="Wrap" Text="Name1"/>
<TextBlock x:Name="TextBlock2" TextWrapping="Wrap" Text="Name2" />
</StackPanel>
</Button>
</Grid>
<StackPanel Grid.Column="1" Grid.Row="0" HorizontalAlignment="Right">
<Button Height="50" Width="50" Background="Transparent" Click="Button_Click">
<Image x:Name="ImageFavorit" Source="/Assets/Stern/VGrau64.png"/>
</Button>
</StackPanel>
</Grid>
Firstly you should replace your ColumnDefinitions to this:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
And secondly remove HorizontalAlignment="Left" from your Grid then you can achieve to what you want:
<Grid VerticalAlignment="Center">
<Button Background="Transparent" HorizontalAlignment="Stretch">
...
Also it seems that you need to set VerticalAlignment="Center" of your StackPanel too:
<StackPanel Grid.Column="1" Grid.Row="0"
HorizontalAlignment="Right" VerticalAlignment="Center">
Update: Based on your comment that you want the text on the left side Set the HorizontalContentAlignment="Left" of the Button:
<Button Background="Transparent" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left">

WPF basic binding

I know this has been asked quite a few times, but no matter how many tutorials I read, I simply cannot understand it. I have a grid with three ColumnDefinitions that can be resized via two GridSplitters. What I want is another grid below it with three ColumnDefinitions that resize as the top grid is being resized (much alike the UI in a program like iTunes). The reason I want separate grids is because eventually, each grid will be its own object and will need drag and drop properties. Here is the Xaml I have written if anyone wants to see what I'm looking at.
<Canvas Width="400" Height="15" Background="AntiqueWhite">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="400" Name='Maingrid'>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140" MinWidth="50"/>
<ColumnDefinition Width="116" MinWidth="50"/>
<ColumnDefinition Width="144" MinWidth="50"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
</Grid.RowDefinitions>
<GridSplitter Grid.Column="0"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Background="Black"
ShowsPreview="True"
Width="2"
/>
<GridSplitter Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Background="Black"
ShowsPreview="True"
Width="2"
/>
<TextBlock Text="Song" Grid.Column="0" Width="30"/>
<TextBlock Text="Song" Grid.Column="1" Width="30"/>
<TextBlock Text="Song" Grid.Column="2" Width="30"/>
</Grid>
</Canvas>
<Canvas Width="400" Height="15" Background="RosyBrown" Margin="58,168,59,138">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="400">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140" MinWidth="50"/>
<ColumnDefinition Width="116" MinWidth="50"/>
<ColumnDefinition Width="144" MinWidth="50"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
</Grid.RowDefinitions>
<TextBlock Text="Song" Grid.Column="0" Width="30"/>
<TextBlock Text="Song" Grid.Column="1" Width="30"/>
<TextBlock Text="Song" Grid.Column="2" Width="30"/>
</Grid>
</Canvas>
Also as a final note, I've looked at endless amounts of tutorials and guides on data binding and my 17 year old brain just can't seem to wrap my head around it. If I could understand how to make a textblock be bound to a variable in my C# codebehind (aka: not setting the textblock's text property in the codebehind, but simply changing the contents of a string), I'd be able to be so much more productive. Thank you to anyone who can help me, I know this question has been asked a million times.
In your c# codebehind, create a property:
private string _songTitle;
public string SongTitle { get { return _songTitle; } set { songTitle = value; } }
In your xaml, create a binding:
<TextBlock Text="{Binding SongTitle}" />
Set the DataContext for your binding (you could put this in the Window.Loaded event)
this.DataContext = this;
Set your property in your code
SongTitle = "Some words and stuff";
That's about it. It can get more complicated, but that's the basics.
This is a way to do it without code behind. Just give your first column definitions names, then bind the lower column definitions widths' to the width of the appropriate column definitions in the first grid. Clean and simple, no code behind to mess with:
<Canvas Width="400" Height="15" Background="AntiqueWhite">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="400" Name='Maingrid'>
<Grid.ColumnDefinitions>
<ColumnDefinition Name="Grid1Col1" Width="140" MinWidth="50"/>
<ColumnDefinition Name="Grid1Col2" Width="116" MinWidth="50"/>
<ColumnDefinition Name="Grid1Col3" Width="144" MinWidth="50"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
</Grid.RowDefinitions>
<GridSplitter Grid.Column="0"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Background="Black"
ShowsPreview="True"
Width="2"
/>
<GridSplitter Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Background="Black"
ShowsPreview="True"
Width="2"
/>
<TextBlock Text="Song" Grid.Column="0" Width="30"/>
<TextBlock Text="Song" Grid.Column="1" Width="30"/>
<TextBlock Text="Song" Grid.Column="2" Width="30"/>
</Grid>
</Canvas>
<Canvas Width="400" Height="15" Background="RosyBrown" Margin="58,168,59,138">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="400">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Width, ElementName=Grid1Col1}" MinWidth="50"/>
<ColumnDefinition Width="{Binding Width, ElementName=Grid1Col1}" MinWidth="50"/>
<ColumnDefinition Width="{Binding Width, ElementName=Grid1Col1}" MinWidth="50"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
</Grid.RowDefinitions>
<TextBlock Text="Song" Grid.Column="0" Width="30"/>
<TextBlock Text="Song" Grid.Column="1" Width="30"/>
<TextBlock Text="Song" Grid.Column="2" Width="30"/>
</Grid>
</Canvas>

avoid fixed size values in grid/stackpanel in xaml in windows phone 8

I am attaching a image
I wanna create gap between MyTask(text) and setting image icon. I can achieve it using margin property. but when my windows phone orientation changes it looks bad. Is there a way that my setting image will always stick to right side and text on left side. how can i create gap between text and image, by avoiding fixed values.
this is my code.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Height="35" Source="/Assets/Icons/MyTasks.png"></Image>
<TextBlock Grid.Column="1" Margin="10,0,0,0" Text="MY TASKS"></TextBlock>
<Image Margin="200,0,0,0" Grid.Column="3" Height="40" Source="/Assets/Icons/Settings.png"></Image>
</Grid>
Check this sample.
This is excerpt of the Pivot template. First and third column definition must be: Width="Auto".
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image
Height="35"
HorizontalAlignment="Left"
Margin="12,0,0,0"
VerticalAlignment="Bottom"
Source="/Assets/Icons/MyTasks.png" />
<ContentControl
ContentTemplate="{TemplateBinding TitleTemplate}"
Content="{TemplateBinding Title}"
Grid.Column="1"
HorizontalAlignment="Left"
Margin="0,0,0,-7"
VerticalAlignment="Center"
Style="{StaticResource PivotTitleStyle}"/>
<Image
Grid.Column="2"
Height="35"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Source="/Assets/Icons/Settings.png" />
</Grid>

LongListSelector focus on item

I have this LongListSelector in my app page:
<Controls:LongListSelector x:Name="searchList" Margin="0,0,0,0" Background="White" SelectionChanged="DidPressSelectSearchList" HorizontalContentAlignment="Stretch" Grid.Row="1">
<Controls:LongListSelector.ItemTemplate>
<DataTemplate>
<local:SearchTemplateSelector Content="{Binding}" HorizontalContentAlignment="Stretch">
<local:SearchTemplateSelector.GoogleSuggestTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Rectangle Height="1" HorizontalAlignment="Stretch" VerticalAlignment="Top" Fill="Black" Opacity="0.3"/>
<TextBlock Text="{Binding}" FontSize="25" Foreground="Black" TextWrapping="Wrap" Grid.Row="1" Margin="0,10"/>
</Grid>
</DataTemplate>
</local:SearchTemplateSelector.GoogleSuggestTemplate>
<local:SearchTemplateSelector.VideoTemplate>
<DataTemplate>
<Grid>
<Rectangle Height="1" HorizontalAlignment="Stretch" VerticalAlignment="Top" Fill="Black" Opacity="0.3" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Margin="0" Source="{Binding Path=ImgUrl}" HorizontalAlignment="Left" Width="100" Height="100" Tag="{Binding idStr}"/>
<Grid Grid.Column="1" Margin="10,0,8,0">
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}" FontSize="20" Foreground="Black" TextWrapping="Wrap" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<StackPanel Orientation="Horizontal" Margin="0,-5,0,0" Grid.Row="1">
<TextBlock Text="Views: " FontSize="20" Foreground="Black"/>
<TextBlock Text="{Binding ViewCount}" FontSize="20" Foreground="Black"/>
</StackPanel>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding TimeStr}" FontSize="20" Foreground="Black" Margin="0,0,0,0" />
<TextBlock Text="Cached" FontSize="20" Foreground="Red" Margin="20,0,0,0" Grid.Column="1" />
</Grid>
</Grid>
</Grid>
</Grid>
</DataTemplate>
</local:SearchTemplateSelector.VideoTemplate>
</local:SearchTemplateSelector>
</DataTemplate>
</Controls:LongListSelector.ItemTemplate>
</Controls:LongListSelector>
And i noticed that when i press a item in the list so the user not have any thing to know which item he pressed, something like focus the item when he press it.
In iPhone the the selected row get blue and when release the blue selection is disappear,there is some equivalent to this in windows phone too?
Use TiltEffect from Silverlight Toolkit for Windows Phone, details are here http://www.geekchamp.com/articles/silverlight-for-wp7-toolkit-tilteffect-in-depth. Also to make an effect more expressive use Button as a container for your ItemTemplate with EmptyButtonStyle http://www.jeff.wilcox.name/2011/10/hyperlinkbutton-empty-style-for-phone/.

Grid in ScrollViewer doesn't scroll horizontally

I think I'm missing something simple here... how do I get a Grid inside a ScrollViewer to scroll horizontally? I've enabled HorizontalScrollMode, and the content is definitely long enough that it runs off the screen, but it doesn't scroll. Here's the offending code (this ScrollViewer is the lone content of a row of the LayoutRoot Grid):
<ScrollViewer Grid.Row="1" VerticalScrollMode="Disabled"
VerticalScrollBarVisibility="Hidden"
HorizontalScrollMode="Enabled">
<Grid Margin="120,0,0,100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="240"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="240"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="240"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="240"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="Download" HorizontalAlignment="Center" Margin="0,0,0,10"/>
<local:BandwidthMeter Grid.Row="1" x:Name="PolicyDown" Grid.Column="0"/>
<TextBlock Grid.Column="2" Text="Upload" HorizontalAlignment="Center"/>
<local:BandwidthMeter Grid.Row="1" x:Name="PolicyUp" Grid.Column="2"/>
<TextBlock Grid.Column="4" Text="Download" HorizontalAlignment="Center"/>
<local:BandwidthMeter x:Name="ActualDown" Grid.Row="1" Grid.Column="4"/>
<TextBlock Grid.Column="6" Text="Upload" HorizontalAlignment="Center"/>
<local:BandwidthMeter x:Name="ActualUp" Grid.Row="1" Grid.Column="6" />
<TextBlock Grid.Column="7" Text="Campus-wide bandwidth usage" HorizontalAlignment="Center"/>
<Image Grid.Column="7" Grid.Row="1" Margin="80,0,0,0" Source="[image URL]" Stretch="UniformToFill"/>
</Grid>
</ScrollViewer>
Add the property HorizontalScrollBarVisibility="Auto" to your ScrollViewer.

Categories