I'm trying to create multiple button with text underneath and have them added to a Stackpanel in code during runtime. I create the buttons based on a List of data. Here's my code:
XAML
<StackPanel x:Name="MainSP" />
C#
foreach (item in ItemList)
{
Button newBtn = new Button();
Image buttonImage = new Image();
buttonImage.Width = 100;
buttonImage.Height = 100;
buttonImage.Stretch = Systems.Windows.Media.Stretch.Uniform;
buttonImage.Source = new BitmapImage(pokemon.ImageURI);
newBtn.Tag = item.Id;
newBtn.Name = String.Format("{0}Button", item.Name);
newBtn.Click += new RoutedEventHandler(newBtn_Click);
FamilyStackPanel.Children.Add(newBtn);
}
I know this is clunky programming. I really want to set up a ControlTemplate in XAML then reuse that when creating the buttons in code. Here's the XAML:
<ControlTemplate x:Key="ButtomTemplate" TargetType="Button">
<Grid Height="108" Width="Auto" Margin = "6,6">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Image Width = "54" Height="54" Stretch="UniformToFill" Grid.Row="0">
<Image.Source>
<BitmapImage UriSource="{Binding ImageUri}" CreateOptions="BackgroundCreation"/>
</Image.Source>
</Image>
<TextBlock Text="{Binding Name}"
Foreground ="{StaticResource PhoneAccentBrush}" />
</Grid>
</ControlTemplate>
I've tried using the controlTemplate like above and then for the bindings, I set the newbtn.DataContext in code.
foreach (Families item in ItemList)
{
Button newBtn = new Button();
newBtn.Template = this.Resources["ButtonTemplate"] as ControlTemplate;
newBtn.Tag = item.Id;
newBtn.Name = String.Format("{0}Button", item.Name);
newBtn.Click += new RoutedEventHandler(newBtn_Click);
newBtn.DataContext = item;
FamilyStackPanel.Children.Add(newBtn);
}
For the data context I've also attempted newBtn.DataContext = ItemList[itemIndex]
but that didn't seem to work. All I get is a blank screen.
So I've figured it out through pure code behind button creation, but I'm trying to use XAML control templates to make it work. Have any ideas?
Thank you!
Creating or manipulating UI elements in procedural code in WPF is almost never
the correct way.
There are exceptions where that would be useful, but this case you're presenting is the simplest case for the ItemsControl.
<ItemsControl ItemsSource="{Binding ItemList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Click="Button_OnClick">
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid Height="108" Width="Auto" Margin = "6,6">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Image Width = "54" Height="54" Stretch="UniformToFill" Grid.Row="0">
<Image.Source>
<BitmapImage UriSource="{Binding ImageUri}" CreateOptions="BackgroundCreation"/>
</Image.Source>
</Image>
<TextBlock Text="{Binding Name}"
Foreground ="{StaticResource PhoneAccentBrush}" />
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Code Behind:
private void Button_OnClick(object sender, RoutedEventArgs e)
{
var button = sender as Button;
var dataitem = button.DataContext as [YourItemclass];
//... here you can perform actions on the dataitem.
}
DataContext
will be also set by WPF to the corresponding data item in the underlying collection.Tag
property or anything like that.StackPanel
is the default ItemsPanel
for the ItemsControl
, but you can change that to another panel (such as WrapPanel
) by setting the ItemsPanel
You can use XamlReader to create xaml with dynamic content. This way you will be able to set any of the property at runtime.
http://msdn.microsoft.com/en-us/library/system.windows.markup.xamlreader(v=vs.110).aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With