51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

使用WinUI3和C#,如何将Observable图像路径列表显示为填充宽度的水平列表?

英文:

With WinUI3 and C#, how do you take a Observable list of Image paths and display them as a horizontal list that fills width?

问题 {#heading}

我有一组图像路径,并希望在单个水平行中显示它们引用的图像。每个图像的宽度应相同,并且它们应根据窗口的调整大小填充窗口的高度或其分配的宽度。

我尝试使用StackPanel来实现这一点,但它不会像具有*大小调整的Grid那样调整图像。

<ItemsControl
    x:Name="HandImages"
    Padding="5"
    ScrollViewer.HorizontalScrollBarVisibility="Visible">

    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Image  
                Source="{Binding}"
                Tapped="ImageTapped"
                Stretch="UniformToFill"
                FlyoutBase.AttachedFlyout="{StaticResource ImagePreviewFlyout}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>

</ItemsControl>

英文:

I have a list of image paths and would like to display the images they refer to in a single horizontal row. The width of each image should be the same and they should all fill the Window's height or their allocated width as the window is resized.

I tried to do this with a StackPanel, but it does not resize the images like a Grid with *-sizing would.

    &lt;ItemsControl
        x:Name=&quot;HandImages&quot;
        Padding=&quot;5&quot;
        ScrollViewer.HorizontalScrollBarVisibility=&quot;Visible&quot;&gt;

        &amp;lt;ItemsControl.ItemsPanel&amp;gt;
            &amp;lt;ItemsPanelTemplate&amp;gt;
                &amp;lt;StackPanel Orientation=&amp;quot;Horizontal&amp;quot;/&amp;gt;
            &amp;lt;/ItemsPanelTemplate&amp;gt;
        &amp;lt;/ItemsControl.ItemsPanel&amp;gt;

        &amp;lt;ItemsControl.ItemTemplate&amp;gt;
            &amp;lt;DataTemplate&amp;gt;
                &amp;lt;Image  
                    Source=&amp;quot;{Binding}&amp;quot;
                    Tapped=&amp;quot;ImageTapped&amp;quot;
                    Stretch=&amp;quot;UniformToFill&amp;quot;
                    FlyoutBase.AttachedFlyout=&amp;quot;{StaticResource ImagePreviewFlyout}&amp;quot;/&amp;gt;
            &amp;lt;/DataTemplate&amp;gt;
        &amp;lt;/ItemsControl.ItemTemplate&amp;gt;

    &amp;lt;/ItemsControl&amp;gt;

答案1 {#1}

得分: 1

你可以使用Windows CommunityToolkit 中的UniformGrid,并将其用作ItemsPanel

  1. 命名你的页面。我们需要这样做来从DataTemplate到页面的Items.Count属性进行绑定。

  2. 安装CommunityToolkit.WinUI.UI.Controls.Primitives NuGet包。

  3. 还有这个:

<ItemsControl ItemsSource="{x:Bind Items, Mode=OneWay}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <toolkit:UniformGrid
                Columns="{Binding ElementName=RootPage, Path=Items.Count}"
                Rows="0" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

英文:

You could use the UniformGrid from the Windows CommunityToolkit and use it as an ItemsPanel.

  1. Name your page. We need to to do this to do bindings from the DataTemplate to the Items.Count property in the page.

  2. Install the CommunityToolkit.WinUI.UI.Controls.Primitives NuGet package.

  3. And this:

&lt;ItemsControl ItemsSource=&quot;{x:Bind Items, Mode=OneWay}&quot;&gt;
    &lt;ItemsControl.ItemsPanel&gt;
        &lt;ItemsPanelTemplate&gt;
            &lt;toolkit:UniformGrid
                Columns=&quot;{Binding ElementName=RootPage, Path=Items.Count}&quot;
                Rows=&quot;0&quot; /&gt;
        &lt;/ItemsPanelTemplate&gt;
    &lt;/ItemsControl.ItemsPanel&gt;
&lt;/ItemsControl&gt;

答案2 {#2}

得分: 0

这是XAML部分的翻译:

    可以以最小的XAML代码以编程方式完成这个任务。以下是我使用的XAML。

    &lt;Grid x:Name="HandGrid"
          RowDefinitions="*"&gt;
        
    &lt;/Grid&gt;




这是C#部分的翻译:

// 然后创建一个视图的可观察集合。我在我的情况下使用了以下代码。

public ObservableCollection<string> images = new();

// 接着,添加代码以响应集合的变化,就像这样。

// 在安全的地方观察集合
viewModel.images.CollectionChanged += HandChanged;
...
private readonly List<ColumnDefinition> ColumnDefinitions = new();
private readonly List<string> ImagePaths = new();
private readonly List<Image> Images = new();

private void HandChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if(e.OldItems != null)
    {
        foreach (string item in e.NewItems)
        {
            HandGrid.ColumnDefinitions.Remove(ColumnDefinitions[^1]);
            ColumnDefinitions.RemoveAt(ColumnDefinitions.Count - 1);
            Images.RemoveAt(ImagePaths.IndexOf(item));
            ImagePaths.Remove(item);
        }
    }

    if (e.NewItems != null)
    {
        foreach (string item in e.NewItems)
        {
            ColumnDefinition cd = new()
            {
                Width = new GridLength(1, GridUnitType.Star)
            };
            ColumnDefinitions.Add(cd);
            HandGrid.ColumnDefinitions.Add(cd);

            Image image = new() {
                Source = new BitmapImage(new Uri(FileUtil.GetFullPath(item))),
                Stretch = Stretch.Uniform,
            };
            
            Images.Add(image);
            ImagePaths.Add(item);
            Grid.SetColumn(image, Images.Count - 1);
            HandGrid.Children.Add(image);
        }
    }
}

这是您要求的翻译,不包含其他内容。 英文:

It is possible to do this programmatically with minimal XAML. Here is the XAML I used.

    &lt;Grid x:Name=&quot;HandGrid&quot;
          RowDefinitions=&quot;*&quot;&gt;

    &amp;lt;/Grid&amp;gt;




Then create an observable collection of the views. I used this in my case.

public ObservableCollection&lt;string&gt; images = new();

Then, add code to respond to changes in the collection like this.

// Observe the collection somewhere where it is safe to do so
viewModel.images.CollectionChanged += HandChanged;
...
        private readonly List&lt;ColumnDefinition&gt; ColumnDefinitions = new();
        private readonly List&lt;string&gt; ImagePaths = new();
        private readonly List&lt;Image&gt; Images = new();

        private void HandChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if(e.OldItems != null)
            {
                foreach (string item in e.NewItems)
                {
                    HandGrid.ColumnDefinitions.Remove(ColumnDefinitions[^1]);
                    ColumnDefinitions.RemoveAt(ColumnDefinitions.Count - 1);
                    Images.RemoveAt(ImagePaths.IndexOf(item));
                    ImagePaths.Remove(item);
                }
            }

            if (e.NewItems != null)
            {
                foreach (string item in e.NewItems)
                {
                    ColumnDefinition cd = new()
                    {
                        Width = new GridLength(1, GridUnitType.Star)
                    };
                    ColumnDefinitions.Add(cd);
                    HandGrid.ColumnDefinitions.Add(cd);

                    Image image = new() {
                        Source = new BitmapImage(new Uri(FileUtil.GetFullPath(item))),
                        Stretch = Stretch.Uniform,
                    };
                    
                    Images.Add(image);
                    ImagePaths.Add(item);
                    Grid.SetColumn(image, Images.Count - 1);
                    HandGrid.Children.Add(image);
                }
            }
        }

赞(0)
未经允许不得转载:工具盒子 » 使用WinUI3和C#,如何将Observable图像路径列表显示为填充宽度的水平列表?