WPF 重复元素

发布于 2024-12-08 19:36:06 字数 610 浏览 0 评论 0原文

我有一个 UserControl,它是一个按钮,具有某些特征,并且我有一个窗口,其中有几个“正常”样式的按钮。在同一个窗口上,我定义了一种样式来覆盖一些正常特征,并且我想要其中的一些(有点像键盘布局)。我拥有的是一个包含 30 行的 UniformGrid,如下所示:

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

行与行之间唯一变化的是标签和内容值。有什么更好的方法来布局像这样的重复内容,其中样式和单击事件不必出现在每一行上?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

反差帅 2024-12-15 19:36:06

更好的方法是在代码中创建一个数据对象,代表您想要在 UI 中显示的 30 个项目,例如:(

class DataObject
{
  string Tag {get;set;}
  string Content {get;set;}
}

我相信您可以想出一个比这更好的名称!)。然后创建 30 个项目并将它们设置为 ItemsControl 的 ItemsSource:

List<DataObject> myObjects = new List<DataObject>();
// populate here
itemsControl.ItemsSource = myObjects

您的 ItemsControl 有一个用于呈现每个项目的 DataTemplate:

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

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>
香橙ぽ 2024-12-15 19:36:06

我猜想 ColinE 的回答有些离谱,我给了他 +1,因为他为我指明了正确的方向 [谢谢],尽管这并没有完全奏效。我最终得到的结果很接近:

在窗口的构造函数中,设置 30 条几乎相同的行:

var numberButtons = Enumerable.Range( 1, 30 )
    .Select( r => new KeyValuePair<string,string>( r.ToString( ), r.ToString( ) ) )
    .ToList( );
numberButtonItems.ItemsSource = numberButtons;

然后,这个 xaml(请注意,“Caption”是我们用户控件的属性,因此它不适用于你):

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

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>
梦境 2024-12-15 19:36:06

另一种(更多的是纯 xaml)解决方案是使用基于您命名的样式的默认样式,并为 ClickEvent 添加 EventSetter:

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

为遇到此答案的其他人提供一个完整的通用示例:

您现有的代码可能如下所示:

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

您可以将其更改为以下内容:

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

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文