I have created a template style for a button that I would like to call for each album in my project.
<Application.Resources>
<Style x:Key="CustomButtonLarge" TargetType="Button">
<Setter Property="Background" Value="Pink" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Width" Value="300" />
<Setter Property="Height" Value="100" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Height" Value="300" />
<Setter Property="Width" Value="200" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="AlbumContentGrid">
<Grid.RowDefinitions>
<RowDefinition Height="200"/>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Image Grid.Row="0" source="null" x:Key="albumCover" />
<Textblock Grid.Row="1" x:Key="Title" Style="{StaticResources CustomForegroundTitleText}"/>
<Textblock Grid.Row="2" x:Key="SubTitle" Style="{StaticResources CustomForegroundSubTitleText}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
When I am in the code behind I want to create this button for each album. So if there is 3 albums, I would like to do a for loop...
int numberOfButtons= 3;
private void Page_Loaded(object sender, RoutedEventArgs e)
{
for (int i = 0; i < numberOfButtons; i++)
{
Button btn = new Button();
Style style = App.Current.Resources["CustomButtonLarge"] as Style;
btn.Style = style;
StackAlbums.Children.Add(btn);
}
}
StackAlbums being a stackPanel in the main grid. For some reason I am not getting anything when I run.
But I'm also not sure how to access the "albumCover" Image so that I can change the source to whatever I need it to be in the code and Change the text values of the Title and SubTitle Textblocks.
The first, you should fix the Style that the Style has the duplicate property width
and Height
.
Then you should make the effect for Background. You should bind it to Grid.
<Grid x:Name="AlbumContentGrid" Background="{TemplateBinding Background}" >
The Grid should be set the Background
to bind the Button
background.
And you should remove all the x:Key
.
If you want to set the Image in code that you should make the data context.
I make a class Foo
to do it.
public class Foo
{
public BitmapImage Image { get; set; }
public string Title { get; set; }
public string SubTitle { get; set; }
}
And I should set it when adding the button.
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
int numberOfButtons = 3;
for (int i = 0; i < numberOfButtons; i++)
{
var foo = new Foo
{
Image = new BitmapImage(new Uri("ms-appx:///Assets/Square44x44Logo.scale-200.png")),
Title = "title" + i,
SubTitle = i.ToString()
};
Button btn = new Button();
Style style = Application.Current.Resources["CustomButtonLarge"] as Style;
btn.Style = style;
btn.DataContext = foo;
StackAlbums.Children.Add(btn);
}
}
The code uses Square44x44Logo.scale-200.png
and you can change it.
Then I should use bind to bind the data context and all the code for CustomButtonLarge is
<Application.Resources>
<Style x:Key="CustomButtonLarge" TargetType="Button">
<Setter Property="Background" Value="Black" />
<Setter Property="Foreground" Value="White" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Margin" Value="10,10,10,10"></Setter>
<Setter Property="Height" Value="200" />
<Setter Property="Width" Value="100" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button" >
<Grid x:Name="AlbumContentGrid" Background="{TemplateBinding Background}" >
<Grid.RowDefinitions>
<RowDefinition Height="200*"/>
<RowDefinition Height="50*"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<Image Grid.Row="0" x:Name="AlbumCover" Source="{Binding Path=Image}"/>
<TextBlock Grid.Row="1" x:Name="Title" Text="{Binding Title}" Foreground="{TemplateBinding Foreground}"/>
<TextBlock Grid.Row="2" x:Name="SubTitle" Text="{Binding SubTitle}" Foreground="{TemplateBinding Foreground}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
I try to run it and clip the screen to you.
If you want to add the click event that you should add some code.
for (int i = 0; i < numberOfButtons; i++)
{
var foo = new Foo
{
Image = new BitmapImage(new Uri("ms-appx:///Assets/Square44x44Logo.scale-200.png")),
Title = "title" + i,
SubTitle = i.ToString()
};
Button btn = new Button();
Style style = Application.Current.Resources["CustomButtonLarge"] as Style;
btn.Style = style;
btn.DataContext = foo;
StackAlbums.Children.Add(btn);
btn.Click += Button_OnClick; // Make the click
}
And you should write Button_OnClick
and add break point to know the user click the button.
private void Button_OnClick(object sender, RoutedEventArgs e)
{
Debug.WriteLine(StackAlbums.Children.Count);
Debug.WriteLine((StackAlbums.Children[0] as FrameworkElement)?.ActualWidth );
Debug.WriteLine((StackAlbums.Children[0] as Button)?.Background?.ToString() ?? "");
}
Edit
If you want to add click animation that you should add the code to VisualStateManager.VisualStateGroups
.
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="AlbumContentGrid" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="AlbumContentGrid"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlHighlightBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Title"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="#aaaaaa" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SubTitle"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="#aaaaaa" />
</ObjectAnimationUsingKeyFrames>
<PointerUpThemeAnimation Storyboard.TargetName="AlbumContentGrid" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="AlbumContentGrid"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="AlbumContentGrid"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Title"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SubTitle"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<PointerDownThemeAnimation Storyboard.TargetName="AlbumContentGrid" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
You should add the code to AlbumContentGrid like this figure.
You can see the click animation when you add the code.