Search code examples
wpftemplatesexpression-blend

How do I edit a WPF button at runtime


So I was using Expression Blend to design my button. I created a new button, edited the template of the button by removing everything within it. Then I added a grid into it and named it "grid". Inside the grid i added a textblock and called it "textBlock". Then i saved the template under Applications.

This is the content in the app.xaml file.

<Style x:Key="CustomButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
        <Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
        <Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Padding" Value="1"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid x:Name="grid" HorizontalAlignment="Left" Height="40" VerticalAlignment="Top" Width="90">
                        <TextBlock x:Name="textBlock" HorizontalAlignment="Left" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Margin="5,5,0,0" Height="25" Width="75" FontSize="17.333"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsDefaulted" Value="true"/>
                        <Trigger Property="IsMouseOver" Value="true"/>
                        <Trigger Property="IsPressed" Value="true"/>
                        <Trigger Property="IsEnabled" Value="false"/>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Basically what I am intending to do is to create a button at runtime, apply this style to the button, go to the template of the button, and change the text property of the textblock in the template of the button.

So for starters, instead of creating a button at runtime, i created one at compile time and named it "customButton". Then I tried to edit the text property of the button's templates' textblock but ran into exceptions.

TextBlock tb = this.customButton.Template.FindName("textBlock", customButton) as TextBlock;
tb.Text = "ASDDDQWEQWEQWE";

Please advise thanks!


Solution

  • I want to create a button to represent a company stock info like Company name, image, and the % increase in stock price all in one single button. So at runtime, ill get the top 10 stocks from an external API and create 10 buttons at runtime with the information and add it to a stackpanel in my main window.

    You need use ListBox and ItemTempate for this kind of scenarios. Try the below code.

     <ListBox x:Name="lstBox">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Button>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding CompanyName}" Margin="0,0,10,0"/>
                            <TextBlock Text="{Binding Percent}" />
                        </StackPanel>
                    </Button>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            ObservableCollection<CompanyModel> companies = new ObservableCollection<CompanyModel>();
            for (int i = 0; i < 10; i++)
            {
                CompanyModel companyModel = new CompanyModel()
                {
                    Percent = i,
                    CompanyName = "Name" + i
                };
                companies.Add(companyModel);
            }
            lstBox.ItemsSource = companies;
        }
    }
    
    class CompanyModel
        {
            public int Percent { get; set; }
            public string CompanyName { get; set; }
        }