【问题标题】:How to dynamically change grid rows and columns according to window size in WPF如何根据WPF中的窗口大小动态更改网格行和列
【发布时间】:2018-08-07 13:29:51
【问题描述】:

我正在制作各种图片库,目前正在通过 C# 将图片动态加载到网格中。如果我不应该使用网格来显示图像,我非常愿意将其更改为更适合的控件,但它需要对窗口大小调整友好。

当我调整窗口大小时,我希望发生以下事情:

  • 所有图像都保持完全相同的大小。它们已经适合网格槽,同时保持其纵横比
  • 网格空间本身也没有调整大小
  • 网格包含更多或更少的行/列,具体取决于窗口可以容纳多少行/列

这意味着,如果将窗口的大小调整为非常薄且非常高,则网格将包含一列(或两列,或者需要多少列)和许多行来显示图像。

如果它很宽,但又不高,那么它只会有一个(或两个,或者需要很多)行和很多列。等等。

不确定是否需要,但我显示图像的代码是:

        for (int i = 0; i < ImageGrid.RowDefinitions.Count; i++)
        {
            for (int j = 0; j < ImageGrid.ColumnDefinitions.Count; j++)
            {
                Image img = new Image();
                BitmapImage bitmap = new BitmapImage();

                using (var fs = new FileStream(path, FileMode.Open)) // open the image
                {
                    bitmap.BeginInit();
                    bitmap.StreamSource = fs;
                    bitmap.CacheOption = BitmapCacheOption.OnLoad;
                    bitmap.EndInit();
                }

                bitmap.Freeze(); // bitmap isn't properly cleaned up and memory leaks can occur if this isn't here

                img.Source = bitmap;

                img.Margin = new Thickness(10);

                img.Stretch = Stretch.Uniform;

                Grid.SetRow(img, i);
                Grid.SetColumn(img, j);

                ImageGrid.Children.Add(img);
            }
        }

我的网格 XAML 是:

    <Grid ShowGridLines="True" Background="DimGray">
        <Grid.ColumnDefinitions>
            <ColumnDefinition MinWidth="175" Width="0"/>
            <ColumnDefinition MinWidth="755" Width="Auto"/>
        </Grid.ColumnDefinitions>

        <Label Name="lblWinSize" Content="Width, Height" 
HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
        <TextBox Name="txtnbox" Style="{StaticResource CustomTxtBox}" 
TextWrapping="NoWrap" Width="Auto" Height="25" VerticalAlignment="Top" 
Margin="10, 20, 10, 0"/>

        <Separator Style="{StaticResource VerticalSeparator}" 
HorizontalAlignment="Right" Height="Auto" Width="2" Margin="0,10,0,10"/>
        <CheckBox Style="{StaticResource CustomCheckBox}" 
HorizontalAlignment="Left" Margin="10,50,0,0" VerticalAlignment="Top"/>
        <Grid Name="ImageGrid" Grid.Column="1" Margin="10,10,0,10" 
ShowGridLines="True" Background="Gray">
            <!--this is the grid where the images would go-->
        </Grid>
    </Grid>

很抱歉该 XAML 的缩进,我无法正确格式化。

行/列在代码中的其他地方定义,但考虑到它会被替换,我认为我不需要粘贴。

同样,如果其他控件更适合,我可以更改为。

【问题讨论】:

    标签: c# wpf xaml dynamic grid


    【解决方案1】:

    你会想要使用一个环绕面板。

    <WrapPanel Orientation="Horizontal">
        <Image Width="50" Height="50" Source="bla.png" />
        <Image Width="50" Height="50" Source="bla.png" />
        <Image Width="50" Height="50" Source="bla.png" />
        <Image Width="50" Height="50" Source="bla.png" />
    </WrapPanel>
    

    【讨论】:

    • 这仍然不起作用。我通过 C# 添加图像,如果方向是水平的,它们都显示在一行中(被窗口边缘切断),如果是垂直的,它们都显示在两行中。我无法通过 xaml 添加图像。 编辑:从包含 WrapPanel 的网格的第二个 ColumnDefinition 中删除 MinWidth 和 Width 值似乎使面板的内容水平动态,但它们仍然被屏幕底部截断。
    • 看看这个然后:stackoverflow.com/questions/3131919/…你会想要绑定你的项目控件并以编程方式添加你的图像
    【解决方案2】:

    使用WrapPanel 使项目的布局在添加新行之前填充窗口的宽度,在ScrollViewer 内允许垂直滚动,这样内容就不会超出可视区域。

    <ScrollViewer>
      <WrapPanel HorizontalAlignment="Center">
        <!-- your items go here -->
      </WrapPanel>
    </ScrollViewer>
    

    如果您的图像是动态添加的,希望您将它们添加到视图可以绑定到的集合中,而不是直接将它们添加到代码隐藏中的视图中...使用 ItemsControl 并为项目定义自己的模板和容器:

    <ScrollViewer>
      <ItemsControl ItemsSource="{Binding Images}" HorizontalAlignment="Center">
        <ItemsControl.ItemTemplate>
          <DataTemplate>
            <Image Source="{Binding ...}" Height="150" Width="150"/>
          </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
          <ItemsPanelTemplate>
            <WrapPanel />
          </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
      </ItemsControl>
    </ScrollViewer>
    

    【讨论】:

      【解决方案3】:

      c#:

      // here set number of images you want to parse
              int qtyOfImages = 10;
      
              for (int i = 0; i < qtyOfImages; i++) {
                  Image img = new Image();
                  BitmapImage bitmap = new BitmapImage();
      
                  using (var fs = new FileStream(path, FileMode.Open)) // open the image
                  {
                      bitmap.BeginInit();
                      bitmap.StreamSource = fs;
                      bitmap.CacheOption = BitmapCacheOption.OnLoad;
                      bitmap.EndInit();
                  }
      
                  bitmap.Freeze(); // bitmap isn't properly cleaned up and memory leaks can occur if this isn't here
      
                  img.Source = bitmap;
      
                  img.Margin = new Thickness(10);
      
                  img.Stretch = Stretch.Uniform;
      
                  //Grid.SetRow(img, i);
                  //Grid.SetColumn(img, j);
      
                  // set width and height so the images stay at the same size
                  img.Width = 300;
                  img.Height = 300;
      
                  ImageGrid.Children.Add(img);
              }
      

      而你的 xaml 会是这样的:

       <Grid ShowGridLines="True" Background="DimGray">
              <Grid.ColumnDefinitions>
                  <ColumnDefinition MinWidth="175" Width="0"/>
                  <ColumnDefinition MinWidth="755" Width="Auto"/>
              </Grid.ColumnDefinitions>
      
              <Label Name="lblWinSize" Content="Width, Height" 
              HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
              <TextBox Name="txtnbox"  Style="{StaticResource CustomTxtBox}"
                  TextWrapping="NoWrap" Width="Auto" Height="25" VerticalAlignment="Top" 
                  Margin="10, 20, 10, 0"/>
      
              <Separator Style="{StaticResource VerticalSeparator}" 
                  HorizontalAlignment="Right" Height="Auto" Width="2" Margin="0,10,0,10"/>
              <CheckBox Style="{StaticResource CustomCheckBox}"
                  HorizontalAlignment="Left" Margin="10,50,0,0" VerticalAlignment="Top"/>
              <!--<Grid Name="ImageGrid" Grid.Column="1" Margin="10,10,0,10" 
                          ShowGridLines="True" Background="Gray">
                      --><!--this is the grid where the images would go--><!--
                  </Grid>-->
      
      
              <!-- set size of wrap panel to your window acutal width -->
              <WrapPanel Orientation="Horizontal" Name="ImageGrid" Width="{Binding ElementName=Window, Path=ActualWidth}">
      
              </WrapPanel>
      
          </Grid>
      

      不要忘记将Name="Window" 放在您的窗口中以使此代码正常工作

      希望有帮助

      【讨论】:

      • 谢谢,这行得通。将 WrapPanel 包装在 @Nick 提到的 Scrollviewer 中,并更改了其他一些东西,现在效果很好。老实说,我完全忘记了 WrapPanels 的存在。很愚蠢,但我会留下这篇文章,以便其他遇到我问题的人看到它。这是图像显示的最终 XAML:pastebin.com/m1JpUfFU
      猜你喜欢
      • 1970-01-01
      • 2012-08-12
      • 1970-01-01
      • 2020-01-14
      • 2017-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-30
      相关资源
      最近更新 更多