UWP:Grid.IsSharedSizeScope和SharedSizeGroup的替代方案

时间:2016-02-07 15:21:22

标签: c# wpf uwp

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

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

2 个答案:

答案 0 :(得分:1)

SharedSizeGroupWPF 独有的,UWP 中不存在。

目标:创建 SharedSizeGroup 的替代方案

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

我们要做什么

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

enter image description here

查看

<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。

答案 1 :(得分:-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; }
}