UWP: Alternative to Grid.IsSharedSizeScope and SharedSizeGroup
Asked Answered
C

3

37

I got the same issue as described in the following, old, forum post: Issue on MSDN
However, for some reason Microsoft decided to remove the functionalities in the answer described there.

What I'm looking for is a ListView with 2+ columns, with the first column containing random data (thus random width elements), making the width of the first column the same as the widest element inside.

Cruickshank answered 7/2, 2016 at 15:21 Comment(4)
I could not (quickly) find out, which functionality you mean to be removed from Microsoft. I thing the approach with SharedSizeGroup should still be valid and working.Seaweed
Only in .NET applications, it has been removed/omitted from UWP.Cruickshank
Any luck finding a solution for that?Earlineearls
What if you use the DataGrid control instead?Framework
G
1

The SharedSizeGroup is a exclusive to WPF and does not exist in UWP.

Goal : create alternative to SharedSizeGroup

In order to know the measure, we need to look at all of the controls and find the maximum.

What we will be making

We use Fody and PropertyChanged.Fody nuget packages. While they are not required for read-only example, it's useful if you start to modifying the data. I add SizeChanged event handler and modify the width directly. You can set a property and bind to instead or create a behavior, but this is how it is done.

enter image description here

View

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

Model and ViewModel

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);
            }
        }
    }
}

The source of this idea originates in Xamarin.

Gilberte answered 5/1, 2021 at 21:38 Comment(0)
N
1

I made mimic for winui, see repo

here's how to use, quite like in WPF

<ListView ItemsSource="{x:Bind DataCollection}" h:ColumnSharedSizeHelper.IsSharedSizeScope="True"
          Width="400" VerticalAlignment="Center">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid ColumnDefinitions="Auto,*">
                <TextBlock Text="{Binding Name}" VerticalAlignment="Center" h:ColumnSharedSizeHelper.SharedSizeGroup="SampleGroup"/>
                <TextBox Grid.Column="1" Text="{Binding Salary}"/>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
Nonattendance answered 28/10, 2023 at 7:47 Comment(0)
R
-3

I think the solution given in this stackoverflow question should do what you want, you would just have to change the first column to Auto instead of *

From the post:


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

and the code behind . just to give a try did not use MVVM

Here's the 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;

    }

and the class that I bind was as follows

 class test
{
    public string Name1 { get; set; }
    public string Name2 { get; set; }
    public string Name3 { get; set; }
}
Rhinelandpalatinate answered 2/12, 2016 at 22:29 Comment(3)
Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline.Graduated
@Graduated I didn't realize stackoverflow was an external resource, sorry. Copied the post.Rhinelandpalatinate
This does not do much but aligns the columns equally. That does not work as a substitute for share size scopes. The whole point of that technique would be to allow different column widths and give them a name that could be used again in the same scope. This answer is far from that functionality.Hydrocele

© 2022 - 2024 — McMap. All rights reserved.