【问题标题】:Creating and filling a NxN grid in UWP Xaml在 UWP Xaml 中创建和填充 NxN 网格
【发布时间】:2016-02-08 22:35:09
【问题描述】:

我正在尝试创建一个 UWP 益智游戏,我想将图片切成 n 个部分,然后以网格的形式显示这些部分。

我的问题是,如何强制某种 NxN 风格。现在我必须最大化窗口才能看到 3x3 网格,如果我缩小任一侧,它将收敛到 2 列,1 列网格。有办法处理吗?

这就是我所做的,我知道 RowDefinition 现在是手动的,直到我找到更好的方法。

<UserControl
    x:Class="PictureSplitter.Views.PictureView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">


        <GridView ItemsSource="{Binding Splitter.PuzzlePositions}">

            <GridView.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Red" BorderThickness="2">
                    <Grid x:Name="picGrid">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"></ColumnDefinition>
                            <ColumnDefinition Width="Auto"></ColumnDefinition>
                            <ColumnDefinition Width="Auto"></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <Image Source="{Binding Piece.ImageSource}" />
                    </Grid>
                </Border>
                </DataTemplate>
            </GridView.ItemTemplate>

        </GridView>

</UserControl>

这是两个示例图像:

【问题讨论】:

  • 你能编译这段代码吗?
  • 是的,否则我将无法发布图片。
  • 我明白了。在 .NET 4.5 中,ItemTemplate 不是 GridView 的一部分。无论如何,我看到你的标签是 UWP,所以它可能在那里工作。

标签: c# wpf xaml uwp


【解决方案1】:

可能有几种方法可以做到这一点,这是另一种方法。我已经修改了 UserControl,以便当页面大小发生变化和/或集合发生变化时,它会自动调整项目大小以将它们显示为方形网格。

UserControl XAML 代码:

<UserControl
    x:Class="MyControls.MyUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MyControls"
    Name="myControl">

    <GridView Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" ItemsSource="{Binding ElementName=myControl, Path=Items}"
              Width="{Binding ElementName=myControl, Path=CurrentWidth}" HorizontalAlignment="Center"
              Height="{Binding Width, RelativeSource={RelativeSource Self}}">
        <GridView.ItemContainerStyle>
            <Style TargetType="GridViewItem">
                <Setter Property="Margin" Value="0"/>
            </Style>
        </GridView.ItemContainerStyle>
        <GridView.ItemTemplate>
            <DataTemplate>
                <Border Padding="10" Width="{Binding ElementName=myControl, Path=ElementSize}" Height="{Binding ElementName=Width, RelativeSource={RelativeSource Self}}">
                    <Border BorderBrush="Red" BorderThickness="3">
                        <Image Source="ms-appx:///Assets/StoreLogo.png" Stretch="UniformToFill"/>
                    </Border>
                </Border>
            </DataTemplate>
        </GridView.ItemTemplate>
    </GridView>
</UserControl>

UserControl 后面的代码:

public sealed partial class MyUserControl : UserControl, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaiseProperty(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

    public IList Items
    {
        get { return (IList)GetValue(ItemsProperty); }
        set { SetValue(ItemsProperty, value); }
    }

    public static readonly DependencyProperty ItemsProperty =
        DependencyProperty.Register("Items", typeof(IList), typeof(MyUserControl),
            new PropertyMetadata(0, (s, e) =>
            {
                if (Math.Sqrt((e.NewValue as IList).Count) % 1 != 0)
                    Debug.WriteLine("Bad Collection");
            }));

    public void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (Math.Sqrt(Items.Count) % 1 != 0) Debug.WriteLine("Bad Collection");
        RaiseProperty(nameof(ElementSize));
    }

    private double currentWidth;
    public double CurrentWidth
    {
        get { return currentWidth; }
        set { currentWidth = value; RaiseProperty(nameof(CurrentWidth)); RaiseProperty(nameof(ElementSize)); }
    }

    public double ElementSize => (int)(currentWidth / (int)Math.Sqrt(Items.Count)) - 1;

    public MyUserControl()
    {
        this.InitializeComponent();
    }
}

主页 XAML:

<Grid>
    <local:MyUserControl x:Name="myControl" Items="{Binding MyItems}"/>
    <Button Content="Add" Click="Button_Click"/>
</Grid>

MainPage后面的代码:

public sealed partial class MainPage : Page
{
    private ObservableCollection<int> myItems = new ObservableCollection<int> { 1, 2, 3, 4, 5, 6, 7, 8 };
    public ObservableCollection<int> MyItems
    {
        get { return myItems; }
        set { myItems = value; }
    }

    public MainPage()
    {
        this.InitializeComponent();
        DataContext = this;
        MyItems.CollectionChanged += myControl.Items_CollectionChanged;
    }

    protected override Size MeasureOverride(Size availableSize)
    {
        myControl.CurrentWidth = Math.Min(availableSize.Height, availableSize.Width);
        return base.MeasureOverride(availableSize);
    }

    private void Button_Click(object sender, RoutedEventArgs e) => MyItems.Add(3);
}

程序以“Bad Collection”开始 - 有 8 个项目,因此您无法从中创建方形网格,但只要您单击提供的按钮 - 集合的计数变为 9,并且网格应该更新自己。

【讨论】:

    【解决方案2】:

    看起来您正在通过 MVVM 执行此操作,所以我认为您需要从 ViewModel 中为您的行和列提供一个属性。然后你需要有一个转换器来为你的作品提供坐标....或者一个附加属性。

    这会给你一个想法:

    <Window.Resources>
        <System:Int64 x:Key="X">3</System:Int64>
        <System:Int64 x:Key="Y">3</System:Int64>
    </Window.Resources>
    
    <Grid x:Name="myGrid" Loaded="Grid_Loaded">
        // You can bind column and row
        // <Button Content="image1" Grid.Column="{Binding column}" Grid.Row="{Binding row}"/>
    
        <Button Content="image1" Grid.Column="0" Grid.Row="0"/>
        <Button Content="image2" Grid.Column="1" Grid.Row="0"/>
        <Button Content="image3" Grid.Column="2" Grid.Row="0"/>
    
        <Button Content="image4" Grid.Column="0" Grid.Row="1"/>
        <Button Content="image5" Grid.Column="1" Grid.Row="1"/>
        <Button Content="image6" Grid.Column="2" Grid.Row="1"/>
    
        <Button Content="image7" Grid.Column="0" Grid.Row="2"/>
        <Button Content="image8" Grid.Column="1" Grid.Row="2"/>
        <Button Content="image9" Grid.Column="2" Grid.Row="2"/>
    </Grid>
    
    private void Grid_Loaded(object sender, RoutedEventArgs e)
    {
        Int64 X = (Int64) this.FindResource("X");
        Int64 Y = (Int64) this.FindResource("Y");
    
        for (Int64 i = 0; i < X; i++)
        { 
            ColumnDefinition c = new ColumnDefinition();
            myGrid.ColumnDefinitions.Add(c);
        }
        for (Int64 i = 0; i < (int)Y; i++)
        {
            RowDefinition r = new RowDefinition();
            myGrid.RowDefinitions.Add(r);
        }
    }
    

    【讨论】:

      【解决方案3】:

      我使用了 ListView 和 GridView 作为它的 View 属性。它工作正常。

      <ListView x:Name="ImageList" Width="210" Height="210">
          <ListView.View>
             <GridView>
                <GridView.ColumnHeaderContainerStyle>
                  <Style TargetType="Control">
                      <Setter Property="Visibility" Value="Collapsed"/>
                  </Style>
                </GridView.ColumnHeaderContainerStyle>
                <GridViewColumn>                            
                   <GridViewColumn.CellTemplate>
                        <DataTemplate>
                             <Image Source="{Binding sq1}"/>
                        </DataTemplate>
                   </GridViewColumn.CellTemplate>
                 </GridViewColumn>
                 <GridViewColumn >
                   <GridViewColumn.CellTemplate>
                         <DataTemplate>
                             <Image Source="{Binding sq2}"/>
                         </DataTemplate>
                    </GridViewColumn.CellTemplate>
                  </GridViewColumn>
      
                  <GridViewColumn >
                      <GridViewColumn.CellTemplate>
                           <DataTemplate>
                               <Image Source="{Binding sq3}"/>
                           </DataTemplate>
                       </GridViewColumn.CellTemplate>
                   </GridViewColumn>    
             </GridView>
        </ListView.View>
      

      var imgBox = new BitmapImage(new Uri(@"/images/cellbkg.jpg", UriKind.Relative));
      var source = new[] { new { sq1 = imgBox, sq2 = imgBox, sq3 = imgBox }, new { sq1 = imgBox, sq2 = imgBox, sq3 = imgBox }, new { sq1 = imgBox, sq2 = imgBox, sq3 = imgBox } };    
      ImageList.ItemsSource = source;
      

      此代码产生以下输出,如果您减小窗口大小,则不会折叠:

      如果这是您想要的,您可以使用以下方法动态添加列。对于 NxN 矩阵,您只需添加 N 列,绑定将负责其余部分:

              GridView view = (GridView)ImageList.View;
              view.Columns.Add(new GridViewColumn());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-14
        • 2019-08-21
        • 2020-07-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多