Nazeerah Banu
Nazeerah Banu

Reputation: 43

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!

Upvotes: 0

Views: 1257

Answers (2)

Jack
Jack

Reputation: 1006

Create a Button Template, like the one you have, and add controls for each of your items:

<ControlTemplate TargetType="{x:Type Button}">
                <StackPanel>
                    <Label Content="{Binding CompanyName}" />
                    <Image Source="{Binding Image}" />
                    <Label Content="{Binding StockChange}" />
                </StackPanel>
</ControlTemplate>

Or you can just add it to the button content:

<Button>
    <Button.Content>
        <StackPanel>
            <Label Content="{Binding CompanyName}" />
            <Image Source="{Binding Image}" />
            <Label Content="{Binding StockChange}" />
        </StackPanel>
    </Button.Content>
</Button

Create an class to hold the data from your API:

public class CompanyInfo 
{
    public string CompanyName;
    public ImageSource Image;
    public string StockChange;
}

Create a ObservableCollection<CompanyInfo> in code-behind or viewmodel to hold the CompanyInfo objects created from your API data:

public ObservableCollection<CompanyInfo> CompanyInfoList = new ObservableCollection<CompanyInfo>();

Create an ItemsControl to create buttons from your list of data:

<ItemsControl ItemsSource="{Binding Path=CompanyInfoList}">

    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>

            //Button with Bindings Goes Here

        </DataTemplate>
    </ItemsControl.ItemTemplate>

</ItemsControl>

And Bobs your uncle. I advise researching some of these things to gain a better understanding of how it all works.

Upvotes: 1

Ayyappan Subramanian
Ayyappan Subramanian

Reputation: 5366

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; }
    }

Upvotes: 1

Related Questions