Получить изображения того же размера после изменения макета сетки - PullRequest
0 голосов
/ 19 сентября 2019

2X5 matrix in which images are not displayed properly3X3 image matrix Я изменяю расположение моей сетки с 3X3 на 2X5.Когда я переключаюсь с 3X3 на 2X5, изображения растягиваются до ширины равномерной сетки, но высота уменьшается вдвое по сравнению с общими вложениями.

Xaml:

<Window x:Class="ImageList1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ImageDisplay" Height="350" Width="825"
        xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
        >
    <Grid x:Name="rootGrid">
        <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
            <StackPanel>
                <StackPanel Orientation="Vertical">

                    <Label Content="Select the display format:" Margin="0,0,0,10"/>
                    <ComboBox x:Name="cmbSelect" Width="100" Margin="-400,-30,0,10" Height="20" SelectionChanged="CmbSelect_SelectionChanged" >
                        <ComboBoxItem>2X2</ComboBoxItem>
                        <ComboBoxItem>3X3</ComboBoxItem>
                    </ComboBox>
                </StackPanel>

              <ListBox Name="UniformGrid" ItemsSource="{Binding ImageList1}" >
                <ListBox.ItemsPanel>
                        <ItemsPanelTemplate>

                            <UniformGrid  Rows="{Binding Path=GridRow, Mode=TwoWay}" Columns="{Binding Path=GridColumn, Mode=TwoWay}"  Width="800" Height="500"/>

                        </ItemsPanelTemplate>
                </ListBox.ItemsPanel>

                <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Vertical" Margin="0.5">

                                <Image Source="{Binding Path}"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Stretch="UniformToFill"/>

                              <TextBlock Background="Black" Foreground="White" Height="18" TextAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,4">
                                <TextBlock Name="ImageName" Margin="0,0,0,1" Foreground="Red" FontWeight="Bold"  Text="{Binding FileName}"/>
                                <TextBlock Name="ImageType" Margin="0,0,0,2" Foreground="LightGoldenrodYellow" FontSize="11">
                                    <TextBlock.Text>
                                        <MultiBinding StringFormat="Type: {0}">
                                            <Binding Path="Extension" />
                                        </MultiBinding>
                                    </TextBlock.Text>
                                </TextBlock>
                                <TextBlock Name="ImageSize" Margin="0,0,0,3" Foreground="Violet">
                                    <TextBlock.Text>
                                        <MultiBinding StringFormat="Size: {0} Bytes">
                                            <Binding Path="Size"/>
                                        </MultiBinding>
                                    </TextBlock.Text>
                                </TextBlock>
                              </TextBlock>
                            </StackPanel>
                        </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ListBox>
            </StackPanel>

        </ScrollViewer>
    </Grid>
</Window>

Код позади:

namespace ImageList1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        private bool handle = true;
        int index = 1;

        public MainWindow()
        {
            InitializeComponent();  
            Window_Loaded();
        }



        public void Window_Loaded()
        {

            // string folderName = "Wallpapers";
            //string folderpath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            var files = Directory.GetFiles(@"D:\ImageList1\ImageList1\Wallpapers");

            ObservableCollection<ImageDetails> images = new ObservableCollection<ImageDetails>();

            foreach (var file in files)
            {
                ImageDetails id = new ImageDetails()
                {
                    Path = file,
                    FileName = System.IO.Path.GetFileName(file),
                    Extension = System.IO.Path.GetExtension(file)
                };

                BitmapImage img = new BitmapImage();
                img.BeginInit();
                img.CacheOption = BitmapCacheOption.OnLoad;
                img.UriSource = new Uri(file, UriKind.Absolute);
                img.EndInit();
                id.Width = img.PixelWidth;
                id.Height = img.PixelHeight;
                FileInfo fi = new FileInfo(file);
                id.Size = fi.Length;
                images.Add(id);
            }


            UniformGrid.ItemsSource = images;

            UniformGrid.SelectedItem = UniformGrid.Items[index];
            UniformGrid.ScrollIntoView(UniformGrid.Items[index]);

        }

        private void CmbSelect_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ComboBox cmb = sender as ComboBox;
            handle = !cmb.IsDropDownOpen;
            Handle();
        }



        private void Handle()
        {
            switch (cmbSelect.SelectedItem.ToString().Split(new string[] { ": " }, StringSplitOptions.None).Last())
            {
                case "2X2": 
                             dynamic_Layout _layout = new dynamic_Layout(2, 5);
                             this.rootGrid.DataContext = _layout;
                             break;
                case "3X3":

                             dynamic_Layout _layout1 = new dynamic_Layout(3, 3);
                             this.rootGrid.DataContext = _layout1;
                             break;

            }
        }

    }
}

dynamic_Layout Класс:

namespace ImageList1
{
    public class dynamic_Layout : INotifyPropertyChanged
    {
        int _gridRow;
        int _gridColumn;

        public event PropertyChangedEventHandler PropertyChanged;

        public int GridRow
        {

            get
            {
                return _gridRow;
            }
            set
            {
                _gridRow = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("GridRow"));
                }
            }
        }

        public int GridColumn
        {

            get
            {
                return _gridColumn;
            }
            set
            {
                _gridColumn = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("GridColumn"));
                }
            }
        }


        public dynamic_Layout(int columns, int rows)
        {

            this.GridColumn = columns;
            this.GridRow = rows;

        }
    }



}

Ожидаемый результат: макет изменяется с 3X3 на 2X5, как и ожидалось, но изображения не отображаются должным образом.

Фактический результат: Изображениеприлагается.

Ответы [ 2 ]

1 голос
/ 20 сентября 2019

Основная проблема, которую я вижу в опубликованном вами коде XAML, заключается в том, что вы задаете ширину и высоту для UniformGrid, в которой размещены изображения.Это также ограничивает оба измерения ListBoxItems.Таким образом, если вы укажете 800 x 500 для сетки 3x3 с 8 элементами, каждый элемент имеет соотношение сторон 8: 5 (8/3: 5/3);для сетки 2x2, отображающей одинаковое количество элементов, каждый элемент имеет соотношение сторон 16: 5 (8/2: 5/4).Поскольку элемент ListBox не может равномерно растягиваться, чтобы соответствовать обоим пропорциям, элементы обрезаются.Изменяя эту строку:

<UniformGrid  Rows="{Binding Path=GridRow, Mode=TwoWay}" Columns="{Binding Path=GridColumn, Mode=TwoWay}"  Width="800" Height="500"/>

на эту:

<UniformGrid  Rows="{Binding Path=GridRow, Mode=TwoWay}" Columns="{Binding Path=GridColumn, Mode=TwoWay}"  Width="800"/>

элементы ListBox ограничены только измерением Width и могут заполнять измерение высоты так, чтобы весь элемент

Результат 3x3: 3x3

Результат 2x2: 2x2

Дальнейшее улучшениеиспользуйте сетку и привязайте ширину UniformGrid к фактической ширине rootGrid.Это позволяет ListBox и ListBoxItems динамически изменять размер вместе с окном.

<Window x:Class="ImageList1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ImageDisplay" Height="350" Width="825"
    xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
    >
<Grid x:Name="rootGrid">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition />
            </Grid.RowDefinitions>
            <StackPanel Orientation="Horizontal">
                <Label Content="Select the display format:"/>
                <ComboBox x:Name="cmbSelect" Width="100"  Height="20" SelectionChanged="CmbSelect_SelectionChanged" SelectedIndex="0" >
                    <ComboBoxItem>2X2</ComboBoxItem>
                    <ComboBoxItem>3X3</ComboBoxItem>
                </ComboBox>
            </StackPanel>
          <ListBox Grid.Row="1" Name="UniformGrid" ItemsSource="{Binding ImageList1}">
            <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <UniformGrid  Rows="{Binding Path=GridRow, Mode=TwoWay}" Columns="{Binding Path=GridColumn, Mode=TwoWay}"  Width="{Binding ElementName=rootGrid, Path=ActualWidth}"/>
                    </ItemsPanelTemplate>
            </ListBox.ItemsPanel>

              <ItemsControl.ItemTemplate>
                  <DataTemplate>
                      <StackPanel Margin="0.5" >

                          <Image Source="{Binding Path}"  />

                          <TextBlock Background="Black" Foreground="White" Height="18" TextAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,4">
                              <TextBlock Name="ImageName" Margin="0,0,0,1" Foreground="Red" FontWeight="Bold"  Text="{Binding FileName}"/>
                              <TextBlock Name="ImageType" Margin="0,0,0,2" Foreground="LightGoldenrodYellow" FontSize="11">
                                  <TextBlock.Text>
                                      <MultiBinding StringFormat="Type: {0}">
                                          <Binding Path="Extension" />
                                      </MultiBinding>
                                  </TextBlock.Text>
                              </TextBlock>
                              <TextBlock Name="ImageSize" Margin="0,0,0,3" Foreground="Violet">
                                  <TextBlock.Text>
                                      <MultiBinding StringFormat="Size: {0} Bytes">
                                          <Binding Path="Size"/>
                                      </MultiBinding>
                                  </TextBlock.Text>
                              </TextBlock>
                          </TextBlock>
                      </StackPanel>
                  </DataTemplate>
              </ItemsControl.ItemTemplate>
        </ListBox>
</Grid>

1 голос
/ 20 сентября 2019

Делая пару предположений о предполагаемом решении:

  1. Изображение должно отображаться полностью, но масштабироваться так, чтобы полностью помещаться на экране сразу.
  2. Панель информации об изображениивсегда должен отображаться

Что не так

Изображение может увеличиваться, чтобы заполнить пространство по горизонтали, и ничто не мешает ему расти по вертикали для поддержания соотношения сторон.StackPanel не ограничивает свои дочерние объекты в направлении укладки - поэтому существует бесконечное количество пространства для расширения в (https://social.msdn.microsoft.com/Forums/vstudio/en-US/6f09d301-0e5a-4cb6-bb75-71cd1cdae5c4/fixing-stackpanels-maxheight-to-containing-control?forum=wpf)

Как это исправить

Вместо StackPanel вынужен элемент управления, который ограничит себя контейнером, в котором он находится - это может быть Grid, DockPanel или что-то еще. Используя DockPanel, я бы закрепил TextBlock снизу (DockPanel.Dock="Bottom" в элементе TextBlock).Это также означает, что он должен быть первым дочерним элементом DockPanel, поскольку дочерние элементы должны быть в том направлении, в котором вы хотите их пристыковать.Причиной того, что TextBlock закрепляется перед Image, является то, что вы хотите установить LastChildFill="True" на DockPanel,поэтому последний элемент на панели будет пытаться заполнить оставшееся доступное пространство - в отличие от StackPanel, который будет увеличиваться, чтобы вместить его дочерние элементы.

Наконец, удалите все инструкции по выравниванию и растяжению на изображении.поведение делает то, что вы хотите больше.

Эти изменения означают заменуваш XAML StackPanel с:

<DockPanel Margin="0.5" LastChildFill="True">

    <TextBlock DockPanel.Dock="Bottom" Background="Black" Foreground="White" Height="18" TextAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,4">
        <TextBlock Name="ImageName" Margin="0,0,0,1" Foreground="Red" FontWeight="Bold"  Text="{Binding FileName}"/>
        <TextBlock Name="ImageType" Margin="0,0,0,2" Foreground="LightGoldenrodYellow" FontSize="11">
            <TextBlock.Text>
                <MultiBinding StringFormat="Type: {0}">
                    <Binding Path="Extension" />
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
        <TextBlock Name="ImageSize" Margin="0,0,0,3" Foreground="Violet">
            <TextBlock.Text>
                <MultiBinding StringFormat="Size: {0} Bytes">
                    <Binding Path="Size"/>
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
    </TextBlock>

    <Image DockPanel.Dock="Bottom" Source="{Binding Path}"/>

</DockPanel>

Проверка кода

В вашем классе dynamic_layout не обязательно иметь INotifyPropertyChanged.Свойства устанавливаются только в конструкторе и никогда не изменяются после привязки к данным.Весь объект заменяется новым dynamic_layout при изменении выпадающего списка.По той же причине привязка в XAML не обязательно должна быть TwoWay, поскольку значение в этих привязках не обновляется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...