【问题标题】:UWP: Alternative to Grid.IsSharedSizeScope and SharedSizeGroupUWP:替代 Grid.IsSharedSizeScope 和 SharedSizeGroup
【发布时间】:2016-05-17 06:25:15
【问题描述】:

我遇到了与以下旧论坛帖子中所述相同的问题:Issue on MSDN
但是,出于某种原因,Microsoft 决定删除那里描述的答案中的功能。

我正在寻找的是一个有 2 列以上的 ListView,第一列包含随机数据(因此是随机宽度元素),使第一列的宽度与内部最宽的元素相同。

【问题讨论】:

  • 我无法(很快)找出您要从 Microsoft 中删除的功能。我认为 SharedSizeGroup 的方法应该仍然有效且有效。
  • 仅在 .NET 应用程序中,已从 UWP 中删除/省略。
  • 运气好能找到解决方案吗?
  • 如果您改用DataGrid 控件会怎样?

标签: c# wpf uwp


【解决方案1】:

SharedSizeGroupWPF 独有的,在 UWP 中不存在。

目标:创建 SharedSizeGroup 的替代方案

为了知道度量,我们需要查看所有控件并找到最大值。

我们将要做什么

我们使用FodyPropertyChanged.Fody nuget 包。虽然只读示例不需要它们,但如果您开始修改数据,它会很有用。我添加SizeChanged 事件处理程序并直接修改宽度。您可以设置一个属性并绑定到,或者创建一个行为,但这就是它的完成方式。

查看

<Page
    x:Class="TestUwp.MainPage"
    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:local="using:TestUwp"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    d:DataContext="{d:DesignInstance Type=local:DataItem}"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    mc:Ignorable="d">

    <ListView ItemsSource="{Binding TestData}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <Grid ColumnSpacing="6" RowSpacing="6">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <TextBlock
                            Grid.Column="0"
                            SizeChanged="LabelSizeChanged"
                            Text="{Binding FirstName}" />
                        <TextBlock Grid.Column="1" Text="{Binding LastName}" />
                    </Grid>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Page>

模型和视图模型

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace TestUwp
{
    public class DataItem : INotifyPropertyChanged
    {
        public DataItem(int id, string firstName, string lastName)
        {
            Id = id;
            FirstName = firstName;
            LastName = lastName;
        }

        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
    }

    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            TestData = new ObservableCollection<DataItem> {
                new DataItem(1, "Pauly", "Thurlborn"),
                new DataItem(2, "Orbadiah", "Ewen"),
                new DataItem(3, "Britni"  ,"Smead"),
                new DataItem(4, "Fionna"  ,"Jennemann"),
                new DataItem(5, "Ashley" ,"Stoddart"),
                new DataItem(6, "Bradford", "Kaesmakers"),
                new DataItem(7, "Maxy" ,"Lemon"),
                new DataItem(8, "Rasia" ,"Comber"),
                new DataItem(9, "Colas" ,"Shepton"),
                new DataItem(10, "Cacilie" ,"Tummons"),
            };
            DataContext = this;
        }
        public ObservableCollection<DataItem> TestData { get; set; }
        private List<ColumnDefinition> _columns = new List<ColumnDefinition>();
        private double _colSize = 0.0;
        private void LabelSizeChanged(object sender, SizeChangedEventArgs e)
        {
            var item = (dynamic)sender;
            var grid = (Grid)item.Parent;
            var column = grid.ColumnDefinitions[0];
            if (!_columns.Contains(column))
            {
                _columns.Add(column);
            }
            var adjustments = new List<ColumnDefinition>();
            if (item.ActualWidth > _colSize)
            {
                _colSize = item.ActualWidth;
                adjustments.AddRange(_columns);
            }
            else
            {
                adjustments.Add(column);
            }
            foreach (var col in adjustments)
            {
                col.Width = new GridLength(_colSize);
            }
        }
    }
}

这个idea的来源源自Xamarin。

【讨论】:

    【解决方案2】:

    我认为this stackoverflow question 中给出的解决方案应该可以满足您的需求,您只需将第一列更改为Auto 而不是*

    来自帖子:


    <Page.Resources>
    
        <DataTemplate x:Key="DataTemplate1"  >
            <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Gray">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <StackPanel Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                    <TextBlock Text="{Binding Name1}"/>
                </StackPanel>
                <StackPanel Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                    <TextBlock Text="{Binding Name2}"/>
    
                </StackPanel>
                <StackPanel Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                    <TextBlock Text="{Binding Name3}"/>
    
                </StackPanel>
            </Grid>
        </DataTemplate>
    </Page.Resources>
    
    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    
        <ListView Name="MyList" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"  VerticalContentAlignment="Stretch" VerticalAlignment="Stretch" Background="Yellow" ItemTemplate="{StaticResource DataTemplate1}">
    
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
                </Style>
            </ListView.ItemContainerStyle>
            <ListView.ItemsPanel>
    
                <ItemsPanelTemplate
                    <!-- Here is the panel that will contain the items -->
                    <StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" Background="Pink" VerticalAlignment="Stretch"/>
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
        </ListView>
    </Grid>
    

    以及后面的代码。刚试了一下没用MVVM

    这是cs

            List<test> li = new List<test>();
        /// <summary>
        /// Invoked when this page is about to be displayed in a Frame.
        /// </summary>
        /// <param name="e">Event data that describes how this page was reached.  The Parameter
        /// property is typically used to configure the page.</param>
        protected async override void OnNavigatedTo(NavigationEventArgs e)
        {
            for (int i = 0; i < 10; i++)
            {
                li.Add(new test()
                {
                    Name1 = "Anobik1" + i.ToString(),
                    Name2 = "Anobik1"                    +i.ToString(),
                    Name3 = "Anobik1"                    +i.ToString()
                });
            }
            MyList.ItemsSource = li;
    
        }
    

    我绑定的类如下

     class test
    {
        public string Name1 { get; set; }
        public string Name2 { get; set; }
        public string Name3 { get; set; }
    }
    

    【讨论】:

    • 鼓励链接到外部资源,但请在链接周围添加上下文,以便您的其他用户了解它是什么以及为什么存在。始终引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。
    • @pableiros 我没有意识到 stackoverflow 是一个外部资源,抱歉。复制了帖子。
    • 这不会做太多,但会平均对齐列。这不能替代共享大小范围。该技术的重点是允许不同的列宽并给它们一个可以在同一范围内再次使用的名称。这个答案与那个功能相去甚远。
    猜你喜欢
    • 2017-03-25
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    • 1970-01-01
    • 2011-06-27
    • 2014-01-24
    • 2011-09-18
    • 2013-10-04
    相关资源
    最近更新 更多