I have a UserControl that is a button, with certain characteristics, and I have a window that has several of these buttons in their "normal" style. On this same window, I have defined a style that overrides some of the normal characteristics, and I want a bunch of them (sort of like a keyboard layout). What I have is a UniformGrid with 30 lines like this:
<wft:TouchButton Style="{StaticResource smallButtonStyle}" Click="TouchButton_Click" Tag="1">1</wft:TouchButton>
<wft:TouchButton Style="{StaticResource smallButtonStyle}" Click="TouchButton_Click" Tag="2">2</wft:TouchButton>
<wft:TouchButton Style="{StaticResource smallButtonStyle}" Click="TouchButton_Click" Tag="3">3</wft:TouchButton>
where the only thing changing from line to line is the Tag and Content values. What is a better way to lay out something repetitive like this, where the Style and Click events do not have to be on every line?
A better way would be to create a data-object in code that represents the 30 items that you want in your UI, for example:
class DataObject
{
string Tag {get;set;}
string Content {get;set;}
}
(I am sure you can come up with a better name than that!). Then create your 30 items and set them as the ItemsSource of an ItemsControl:
List<DataObject> myObjects = new List<DataObject>();
// populate here
itemsControl.ItemsSource = myObjects
Your ItemsControl has a DataTemplate that is used to render each item:
<ItemsControl x:Name="itemsControl">
<!-- specify the panel that is the container for your items -->
<ItemsControl.ItemPanelTemplate>
<ItemPanelTemplate>
<UniformGrid/>
</ItemPanelTemplate>
</ItemsControl.ItemPanelTemplate>
<!-- specify the template used to render each item -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<wft:TouchButton Style="{StaticResource smallButtonStyle}"
Click="TouchButton_Click"
Tag="{Binding Tag}"/
Content="{Binding Content}">
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I guessed that ColinE's response was off the top of his head, and I gave him a +1 for pointing me in the right direction [THANKS], although it didn't exactly work. What I ended up with was close:
In the constructor for the window, to set up the 30 almost-identical lines:
var numberButtons = Enumerable.Range( 1, 30 )
.Select( r => new KeyValuePair<string,string>( r.ToString( ), r.ToString( ) ) )
.ToList( );
numberButtonItems.ItemsSource = numberButtons;
Then, this xaml (note that "Caption" is a property of our user control, so it won't work for you):
<ItemsControl Grid.Row="1" x:Name="numberButtonItems">
<ItemsControl.ItemsPanel>
<!-- specify the panel that is the container for your items -->
<ItemsPanelTemplate>
<UniformGrid Rows="4" Columns="10" HorizontalAlignment="Left" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- specify the template used to render each item -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<wft:TouchButton Style="{StaticResource smallButtonStyle}"
Click="TouchButton_Click"
Tag="{Binding Key}"
Caption="{Binding Value}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
An alternative (more of a pure xaml) solution would be to use a default style BasedOn your named style, and adding an EventSetter for the ClickEvent:
<UniformGrid>
<UniformGrid.Resources>
<Style TargetType="{x:Type wft:TouchButton}" BasedOn="{StaticResource smallButtonStyle}">
<EventSetter Event="Click" Handler="chButton_Click" />
</Style>
</UniformGrid.Resources>
<wft:TouchButton Tag="1">1</wft:TouchButton>
<wft:TouchButton Tag="2">2</wft:TouchButton>
<wft:TouchButton Tag="3">3</wft:TouchButton>
</UniformGrid>
A complete generic example for anyone else who runs across this answer:
Your existing code might look like this:
<Window x:Class="TestWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
<Window.Resources>
<Style x:Key="myButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red" />
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<Button Style="{StaticResource myButtonStyle}" Content="1" Click="Button_Click" />
<Button Style="{StaticResource myButtonStyle}" Content="2" Click="Button_Click" />
<Button Style="{StaticResource myButtonStyle}" Content="3" Click="Button_Click" />
<Button Style="{StaticResource myButtonStyle}" Content="4" Click="Button_Click" />
<Button Style="{StaticResource myButtonStyle}" Content="5" Click="Button_Click" />
<Button Style="{StaticResource myButtonStyle}" Content="6" Click="Button_Click" />
</StackPanel>
</Grid>
</Window>
And you can change it to the following:
<Window x:Class="TestWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
<Window.Resources>
<Style x:Key="myButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red" />
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<StackPanel.Resources> <!-- Adding style below will apply to all Buttons in the stack panel -->
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource myButtonStyle}">
<EventSetter Event="Click" Handler="Button_Click" />
</Style>
</StackPanel.Resources>
<Button Content="1" />
<Button Content="2" />
<Button Content="3" />
<Button Content="4" />
<Button Content="5" />
<Button Content="6" />
</StackPanel>
</Grid>
</Window>
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