【问题标题】:Problems getting spreadsheet grid look with Viewbox and ListView in UWP Project在 UWP 项目中使用 Viewbox 和 ListView 获取电子表格网格外观的问题
【发布时间】:2017-03-29 13:03:15
【问题描述】:

我正在尝试创建一个“类似电子表格”的网格,其列标题显示来自一组播放器对象的信息,其中单元格内容的大小已最大化。为此,我有一个带有ListView 绑定到Player 对象集合的UWP 应用程序。 ListView.ItemsPanel 使用从here 获得的UniformGridPanel

UniformGridPanel 有一个Rows 属性绑定到可以变化的玩家数量和一个列。 UniformGridPanel 用于显示所有玩家,赋予每个玩家物品相同的高度,因此没有玩家被部分显示并且没有滚动。 UniformGridPanel 工作正常。

ListView.ItemTemplate 是一个具有固定数量的列的Grid,表示每个玩家的数据。

我的问题是:

  1. 每个“单元”中的信息不够大。我希望每个“单元格”内容最大化,并且网格布局保持电子表格一样,即正方形,行和列对齐。
  2. 我不知道如何将标题放在与每列中的单元格对齐的每列上。

所以显示如下所示。这是最接近我想要的,但对于单元格内容和列标题的大小。

如您所见,数字和字母更大的空间很大。我在 XAML 中使用Viewbox 尝试了许多变体。例如,将ListView 包装在Viewbox 中会产生这样的结果,因为列未对齐。

如果我在每个定义“单元格”的Bordercontrol 周围加上Viewbox,我仍然会遇到布局问题。

尽管我在 UWP 上下文中遇到问题,但我还是用 WPF 标记了这篇文章,以防有人在该领域有类似的经验,可以在这里应用。

代码隐藏:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        ObservableCollection<Player> players = new ObservableCollection<Player>();

        players.Add(new Player("John", "Smith",1,99,11,1));
        players.Add(new Player("Fred", "Blogs", 19, 25, 11, 1));
        players.Add(new Player("Andrew", "Sykes", 19, 25, 11, 2));
        players.Add(new Player("Dean", "Andrews", 19, 179, 11, 1));

        this.DataContext = players;
    }
}

XAML:

<Grid x:Name="root" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition/>
    </Grid.RowDefinitions>
    
    <Grid x:Name="grdPlayers" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
        <!--<Viewbox VerticalAlignment="Stretch" HorizontalAlignment="Stretch" StretchDirection="Both" Stretch="Fill">-->
        <ListView  x:Name="lvwPlayers"
                Padding="0"
                BorderBrush="Red"
                BorderThickness="5"
                            ItemsSource="{Binding}"
                            SelectionMode="None"
                            ScrollViewer.VerticalScrollMode="Disabled"
                            ScrollViewer.VerticalScrollBarVisibility="Hidden"
                            ScrollViewer.HorizontalScrollBarVisibility="Hidden" 
                            ScrollViewer.HorizontalScrollMode="Disabled"
                            VerticalAlignment="Stretch"
                            VerticalContentAlignment="Stretch"
                            HorizontalAlignment="Stretch"
                            HorizontalContentAlignment="Stretch">

           
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="Padding" Value="0"/>
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
                </Style>
            </ListView.ItemContainerStyle>

            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <local:UniformGrid x:Name="pnlPlayer" Rows="{Binding Count}" Columns="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>


            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid x:Name="grdPlayerRow">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Border Grid.Column="0" BorderBrush="Black" BorderThickness="1"  Background="Green" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            <TextBlock Text="{Binding Initials}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
                        </Border>
                        <Border Grid.Column="1" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            <TextBlock Text="{Binding HighScore}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
                        </Border>
                        <Border Grid.Column="2" BorderBrush="Black" BorderThickness="1"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            <TextBlock Text="{Binding LowScore}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
                        </Border>
                        <Border Grid.Column="3" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            <TextBlock Text="{Binding Average}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
                        </Border>
                        <Border Grid.Column="4" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            <TextBlock Text="{Binding TonCount}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
                        </Border>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <!--</Viewbox>-->
    </Grid>
</Grid>

玩家代码:

public class Player : INotifyPropertyChanged
{

    public Player(string firstName, string lastName, int low, int high, int avg, int tonCount)
    {
        FirstName = firstName;
        LastName = lastName;
        LowScore = low;
        HighScore = high;
        Average = avg;
        TonCount = tonCount;
    }

    protected void OnPropertyChanged([CallerMemberName] string caller = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(caller));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private int _tonCount;
    public int TonCount
    {
        get { return _tonCount; }
        set
        {
            _tonCount = value;
            OnPropertyChanged();
        }
    }


    private double _average;
    public double Average
    {
        get { return _average; }
        set
        {
            _average = value;
            OnPropertyChanged();
        }
    }

    private int _lowScore;
    public int LowScore
    {
        get { return _lowScore; }
        set
        {
            _lowScore = value;
            OnPropertyChanged();
        }
    }

    private int _highScore;
    public int HighScore
    {
        get { return _highScore; }
        set
        {
            _highScore = value;
            OnPropertyChanged();
        }
    }


    public string FullName
    {
        get { return $"{FirstName} {LastName}"; }
    }

    private string _firstName = string.Empty;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            OnPropertyChanged();
            OnPropertyChanged("Initials");
        }
    }

    private string _lastName = string.Empty;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            _lastName = value;
            OnPropertyChanged();
            OnPropertyChanged("Initials");
        }
    }

    public string Initials
    {
        get
        {
            return FirstName.Substring(0, 1) + LastName.Substring(0, 1).ToUpper();
        }
    }

    public override string ToString()
    {
        return FullName;
    }
}

更新:

@Grace Feng,您在分配 DataContext 之前使用 lvwPlayers 加载事件的答案给出了以下输出,这不是我想要的。首先,行的高度无缘无故??:

【问题讨论】:

    标签: c# wpf layout uwp uwp-xaml


    【解决方案1】:

    根据您的描述,我认为没有必要使用UniformGridPanel,您可以简单地自定义一个Grid,使其高度等于宽度。例如,像这样创建TemplatedControl

    public sealed class SquareGrid : Grid
    {
        public SquareGrid()
        {
            this.Loaded += SquareGrid_Loaded;
        }
    
        private void SquareGrid_Loaded(object sender, RoutedEventArgs e)
        {
            this.Height = this.ActualWidth;
        }
    }
    

    对于“我不知道如何在每个列上放置与每列中的单元格对齐的标题。”的问题,我认为您可以将它们设置为 HeaderListView .但是使用ViewBox 使Text 填充大小是非常明智的。演示来了:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Width="900">
        <ListView  x:Name="lvwPlayers"
                Padding="0"
                BorderBrush="Red"
                BorderThickness="5"
                            ItemsSource="{Binding}"
                            SelectionMode="None"
                            ScrollViewer.VerticalScrollMode="Disabled"
                            ScrollViewer.VerticalScrollBarVisibility="Hidden"
                            ScrollViewer.HorizontalScrollBarVisibility="Hidden"
                            ScrollViewer.HorizontalScrollMode="Disabled"
                            VerticalAlignment="Stretch"
                            VerticalContentAlignment="Stretch"
                            HorizontalAlignment="Stretch"
                            HorizontalContentAlignment="Stretch">
    
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="Padding" Value="0" />
                    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    <Setter Property="VerticalContentAlignment" Value="Stretch" />
                </Style>
            </ListView.ItemContainerStyle>
    
            <!--<ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <local:UniformGrid x:Name="pnlPlayer" Rows="{Binding Count}" Columns="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>-->
            <ListView.Header>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <local:SquareGrid BorderBrush="Black" BorderThickness="1">
                        <Viewbox>
                            <TextBlock Text="Initials" />
                        </Viewbox>
                    </local:SquareGrid>
                    <local:SquareGrid BorderBrush="Black" BorderThickness="1" Grid.Column="1">
                        <Viewbox>
                            <TextBlock Text="HighScore" />
                        </Viewbox>
                    </local:SquareGrid>
                    <local:SquareGrid BorderBrush="Black" BorderThickness="1" Grid.Column="2">
                        <Viewbox>
                            <TextBlock Text="LowScore" />
                        </Viewbox>
                    </local:SquareGrid>
                    <local:SquareGrid BorderBrush="Black" BorderThickness="1" Grid.Column="3">
                        <Viewbox>
                            <TextBlock Text="Average" />
                        </Viewbox>
                    </local:SquareGrid>
                    <local:SquareGrid BorderBrush="Black" BorderThickness="1" Grid.Column="4">
                        <Viewbox>
                            <TextBlock Text="TonCount" />
                        </Viewbox>
                    </local:SquareGrid>
                </Grid>
            </ListView.Header>
    
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid x:Name="grdPlayerRow">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <local:SquareGrid Grid.Column="0" BorderBrush="Black" BorderThickness="1" Background="Green" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            <Viewbox>
                                <TextBlock Text="{Binding Initials}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
                            </Viewbox>
                        </local:SquareGrid>
                        <local:SquareGrid Grid.Column="1" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            <Viewbox>
                                <TextBlock Text="{Binding HighScore}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
                            </Viewbox>
                        </local:SquareGrid>
                        <local:SquareGrid Grid.Column="2" BorderBrush="Black" BorderThickness="1"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            <Viewbox>
                                <TextBlock Text="{Binding LowScore}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
                            </Viewbox>
                        </local:SquareGrid>
                        <local:SquareGrid Grid.Column="3" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            <Viewbox>
                                <TextBlock Text="{Binding Average}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
                            </Viewbox>
                        </local:SquareGrid>
                        <local:SquareGrid Grid.Column="4" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            <Viewbox>
                                <TextBlock Text="{Binding TonCount}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
                            </Viewbox>
                        </local:SquareGrid>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
    

    渲染图像:

    【讨论】:

    • 您好@Grace Feng,很抱歉您的帖子回复晚了。您的解决方案几乎就在那里,但并不完全。您的解决方案的问题是,当有很多玩家并且名为 lvwPlayers 的 ListView 包含在另一个 Grid 中的 Grid 中时,ListView 不会显示所有玩家。事实上,尽管没有滚动,您可以点击进入ListView 并使用箭头键移动到“隐藏”的。这不是我想要的。我希望展示所有球员。你能提供任何帮助吗?
    • @Cleve,您的意思是您的ListView 不能向下滚动以显示更多项目?那是因为你禁用了里面的ScrollViewerScrollViewer.VerticalScrollMode="Disabled",我以为你设计的就是这样。
    • 嗨@Grace Feng,很抱歉我没有很好地解释自己。我不希望 ListView 滚动。我希望所有玩家(+标题行)在ListView父级允许的空间中立即可见。因此,无论那里有多少玩家,它们仍然是立即可见的。在这样做时,我接受项目的大小可能会缩小以适应可用空间。
    • @Cleve,如果在添加到ListView 之前知道项目数并且以后不会删除或添加任何项目,那么很简单。如果没有,我认为您将需要重新计算并重新渲染您的 ListView,这要复杂得多。
    • 冯,在添加到ListView之前,项目数是已知的,不会添加或删除任何项目。请问您能提供解决方案吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    • 2014-04-24
    • 2017-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多