WPF:如何动态创建一个具有连续数字的x行和y列的网格

nuypyhwy  于 2023-06-24  发布在  其他
关注(0)|答案(5)|浏览(170)

我对wpf和c#完全是新手,所以如果这是一个超级琐碎的问题,请原谅。我正在尝试创建一个相当简单的控件。

此网格将始终包含连续的数字,前面有一个彩色矩形。点击灰色矩形将改变其颜色,并将文本设置为粗体(稍后我将处理这些触发器)。
现在,我只需要弄清楚如何动态地创建这个控件。当程序启动时,它需要一次创建这个控件,然后大小不会改变。我需要告诉它列和行的数量(每列可能总是有8个元素),并让它填充具有特定字体样式/矩形颜色的连续数字。
我尝试了为矩形/标签组合创建一个stackpanel UserControl,将样式传递给它,然后在网格的特定行/列中添加32个这样的UserControl。但我需要网格的大小是动态的,所以我需要在代码中加入一些for循环。
谢谢!

7y4bm7vi

7y4bm7vi1#

我会从ItemsControl开始
您可以为它提供一个项目集合,它会按照您想要的方式呈现每个项目,并显示在您想要的任何面板中。
例如,你可能有这样的东西

<ItemsControl ItemsSource="{Binding MyCollection}">

    <!-- This panel will be used to hold the items -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Rows="8" Columns="8" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <!-- Each item will be drawn using this template -->
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Text="{Binding }" Style="{StaticResource MyButtonStyle}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

UniformGrid的RowsColumns属性是DependencyProperties,因此您可以将它们绑定到DataContext上的属性以使它们成为动态的。
UniformGrid的唯一问题是it only arranges items Horizontally。如果你想垂直显示它们,你可以创建一个custom UniformGrid,或者切换到一个不同的面板,如WrapPanel。如果你是WPF面板的新手,我建议阅读WPF Layouts - A Quick Visual Start
ItemTemplate可以是任何东西。就我个人而言,我会使用一个按钮,这样你就有了点击或命令行为来处理这个事件,只要覆盖按钮的模板,看起来就像你想要的。这是一个简单的任务,包括你的触发器在那里太。
如果你想要选择行为,我建议你从ItemsControl切换到ListBox,并以同样的方式覆盖模板,但听起来你并不需要,所以我认为ItemsControl更好:)

ntjbwcob

ntjbwcob2#

我会尝试使用listview并将模板更改为您想用于元素的样式。
若要限制一行中可以使用的项数,请使用

<ListView.ItemsPanel>
    <ItemsPanelTemplate>
        <UniformGrid Columns="3" />
    </ItemsPanelTemplate>
  </ListView.ItemsPanel>

这样你总是会得到一行中的3个元素,比如
123
456
要使3动态化,您可以在代码隐藏/视图模型中将其数据绑定为某个值
要在listview中动态创建元素,可以将对象添加到列表/可观察集合中,然后通过

listviewname.ItemSource=ListName;

或者随便你。它们将根据你告诉网格有多少列来排列。添加32个项目(统一网格为4)导致
一二三四
五六七八
九一零一一二
...

o7jaxewo

o7jaxewo3#

在你的页面上,你必须创建一个“主”元素,例如一个网格。给予它一个名字,这样我们就可以通过代码访问它。这里我给它起了根的名字
所以你会得到类似于

<Page
    ... >

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
          x:Name="root">

    </Grid>
</Page>

然后,在此页面的.cs文件中,您必须使用下面的代码创建一个函数。您可以在MainPage()函数上调用此函数。
此循环将创建一个包含动态网格行的网格列

// Create a Grid and add it to a component of your page
Grid mainGrid = new Grid();
root.Children.Add(mainGrid); 

for (int i = 0; i < 8; i++)
{
    // I am creating a Grid with a TextBlock inside, 
    // it will have the same apperance as a Rectangle, 
    // but this way you can have a Text inside
    Grid g = new Grid();
    TextBlock tb = new TextBlock();

    tb.Text = i.ToString();
    g.Children.Add(tb);

    // Here you set the Grid properties, such as border and alignment
    // You can add other properties and events you need
    g.BorderThickness = new Thickness(1);
    g.BorderBrush = new SolidColorBrush(Colors.Black);
    g.HorizontalAlignment = HorizontalAlignment.Stretch;
    g.VerticalAlignment = VerticalAlignment.Stretch;

    // Add the newly created Grid to the outer Grid
    mainGrid.RowDefinitions.Add(new RowDefinition());
    mainGrid.Children.Add(g);

    // Set the row of the Grid. 
    Grid.SetRow(g, i);
}

我使用了网格而不是矩形,因为矩形不能有孩子。
创建其他列也一定很容易,使用与创建行相同的逻辑。

a6b3iqyw

a6b3iqyw4#

对我来说,解决方案与上面的方案非常相似,但是我必须在后面的代码中绑定ItemsSource。

<!-- This panel will be used to hold the items -->
<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <StackPanel/>
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

<!-- Each item will be drawn using this template -->
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <!--Here is the big deal I think. Desing your template according to what you need. In this case, a grid with 1 default row and column will work--> 
        <Grid>
            <!--Reading object property called "Exchange" and setting its value into a text block-->
            <TextBlock
                Margin="10, 10, 10, 40" FontSize="16" 
                HorizontalAlignment="Center"
                VerticalAlignment="Center" Foreground="GreenYellow" Text="{Binding Exchange}" />    
        </Grid>
    </DataTemplate>
</ItemsControl.ItemTemplate>

然后在page.cs中,我在构造函数中完成了绑定权限。但是你可以随时绑定

List<Bot> Bots = new()
{
    new Bot
    {
        Exchange = "Binance"
    },
    new Bot
    {
        Exchange = "Kukoin"
    }
};

ItemsControlName.ItemsSource = Bots; // I HAD to bind here. Could not make it work another way.

在我的例子中,我使用了一个名为Bot的简单类列表,其中有一个名为Exchange的属性。就像这样

public class Bot
{
   public string Exchange { get; set; }
}

然后我得到了它:

0ve6wy6x

0ve6wy6x5#

对我来说很好:

<ListView x:Name="MyListView"
              AlternationCount="2"
              ItemsSource="{Binding Entities}">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListViewItem">
                            <Border x:Name="ItemBorder"
                                    Background="{TemplateBinding Background}"
                                    BorderBrush="WhiteSmoke"
                                    BorderThickness="1,0,1,1">
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto" />
                                        <ColumnDefinition Width="10" />
                                        <ColumnDefinition Width="*" />
                                    </Grid.ColumnDefinitions>

                                    <TextBlock Text="{Binding Name}" VerticalAlignment="Center" HorizontalAlignment="Center"
                                               Width="200" TextAlignment="Center"
                                           Foreground="BlueViolet"/>

                                    <!--Columns-->
                                    <ItemsControl 
                                    Grid.Column="2"
                                    ItemsSource="{Binding PermissionColumns.Values}">
                                        <!--Definition how your item should look like-->
                                        <ItemsControl.ItemTemplate>
                                            <DataTemplate>
                                                <TextBlock Text="{Binding ResourceKey}"  Width="230"
                                                           Margin="10,0"
                                                           TextAlignment="Justify"/>
                                            </DataTemplate>
                                        </ItemsControl.ItemTemplate>

                                        <!--Definition how should look like your columns-->
                                        <ItemsControl.ItemsPanel>
                                            <ItemsPanelTemplate>
                                                <StackPanel Orientation="Horizontal" 
                                                            IsItemsHost="True"/>
                                            </ItemsPanelTemplate>
                                        </ItemsControl.ItemsPanel>
                                    </ItemsControl>
                                </Grid>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                                    <Setter Property="Background" Value="White" />
                                </Trigger>
                                <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                                    <Setter Property="Background" Value="LightGray" />
                                </Trigger>
                                <Trigger Property="IsSelected" Value="True">
                                    <Setter Property="Background" Value="LightBlue" />
                                </Trigger>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Background" Value="DeepSkyBlue" />
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListView.ItemContainerStyle>
        
        <ListView.Style>
            <Style TargetType="ListView">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListView">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto" />
                                    <RowDefinition Height="*" />
                                </Grid.RowDefinitions>

                                <!--Headers-->
                                <ItemsControl
                                    Background="Green"
                                    ItemsSource="{Binding DataContext.EntityHeaders}">
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <StackPanel Orientation="Horizontal"
                                                        IsItemsHost="True"/>
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <TextBlock Text="{Binding}" Width="230" TextAlignment="Center"
                                                       FontWeight="Bold"/>
                                        </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                </ItemsControl>

                                <!--Items (** Here is items which we are defining in ItemsConainerStyle >>> above)-->
                                <ScrollViewer HorizontalScrollBarVisibility="Disabled"
                                              VerticalScrollBarVisibility="Auto"
                                              Grid.Row="1">
                                    <ItemsPresenter />
                                </ScrollViewer>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListView.Style>
    </ListView>

相关问题