How to adjust all ListViewItem to the widest TextBox

BitSmithy 2,141 Reputation points
2024-08-01T14:20:52.5066667+00:00

Hello

I have a such ListView

                            <ListView x:Name="lvSendingActionReceivers" Grid.Row="1"                                                                  
                                      ItemsSource="{x:Bind DataSource, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                      >
                                <ListView.ItemTemplate>
                                    <DataTemplate x:DataType="local:DataSourceClass">
                                        
                                        <Grid HorizontalAlignment="Stretch">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="Auto"></ColumnDefinition>
                                                <ColumnDefinition Width="*"></ColumnDefinition>
                                            </Grid.ColumnDefinitions>
                                            <TextBox Grid.Column="0"
                                                Text="{x:Bind Name}"
                                                     AcceptsReturn="True"                                                       
                                                     TextWrapping="Wrap"
                                                     HorizontalAlignment="Stretch"
                                                     DataContext=""
                                                     ></TextBox>
                                            <TextBox Grid.Column="1"
                                                Text="{x:Bind Desc}"                                                       
                                                     AcceptsReturn="True"                                                       
                                                     TextWrapping="Wrap"
                                                     HorizontalAlignment="Stretch"                                                     
                                                     ></TextBox>
                                        </Grid>
                                        
                                    </DataTemplate>
                                </ListView.ItemTemplate>
                                <ListView.ItemContainerStyle>
                                    <Style TargetType="ListViewItem">
                                        <Setter Property="HorizontalContentAlignment"  Value="Stretch"></Setter>
                                    </Style>
                                </ListView.ItemContainerStyle>
                            </ListView>

In this solution TextBoxes in every row have different width (in depenedency from its Text property).

I am looking for solution where width of every first TextBox will be adjusted to the widest TextBox but no more than 200 epx.

Could any one explain me how to meet such requirement.

Universal Windows Platform (UWP)
{count} votes

2 answers

Sort by: Most helpful
  1. BitSmithy 2,141 Reputation points
    2024-08-08T15:36:13.4433333+00:00

    I dont want to use DataGrid in my scenario, I want to use ListView.

    Currently I invented solution described below, but in my solution I must join bussines logic and UI logic in data source calss . The second problem is that I calculate column width using not very good method.

    So I dont like this solution. If anyone can find solution where business logic and UI logic arent joind please show me it.

    Mu current solution:

    In DataSource class I added property: double NameColumnWidth {get; set} = 100.

    Next I bind this property to TextBox: <TextBox Width="{x:Bind NameColumnWidth, Mode=OneWay}"

    Next after loading data to ItemsSource I use two iterations. First finds the widest column and next one sets this width to all data items.

    Next x:Bind transfers column widths to UI.

                        double nameColumnWidth = 100;
                        foreach (var sar in dataSourceList)
                        {
                            double nameWidth = sar.Name.Length * 5;
                            if (NameWidth > 100 && NameWidth < 250)
                                nameColumnWidth = nameWidth;
                            else
                                nameColumnWidth = 250;
                        }
    
                        if (nameColumnWidth > 100)
                        {
                            foreach (var sar in dataSourceList)
                            {
                                if (nameColumnWidth != 100)
                                    sar.NameColumnWidth = nameColumnWidth;
                            }
                        }
     
    
    
    1 person found this answer helpful.
    0 comments No comments

  2. Junjie Zhu - MSFT 18,486 Reputation points Microsoft Vendor
    2024-08-05T09:06:37.0333333+00:00

    Hi @BitSmithy ,

    Your requirement is difficult to achieve in Listview. I tried to get the width of the textbox like this, but it gave me the default value instead of the real width.

    private void TextBoxRow1_Loaded(object sender, RoutedEventArgs e)
    {
        TextBox textBox = (TextBox)sender;
        row1maxWidth = Math.Max(row1maxWidth, textBox.ActualWidth);
        //always get 64*32 here
        row1maxWidth = Math.Min(row1maxWidth, 200); // Cap the width at 200 epx
    }
    

    If you want to get a stable table, it is recommended that you use DataGrid.

    
    <controls:DataGrid x:Name="EmployeeGrid"
              ItemsSource="{x:Bind DataSource}"
              AutoGenerateColumns="False">
        <controls:DataGrid.Columns>
            <controls:DataGridTextColumn Header="Name"
                                         MaxWidth="200"
                                         Binding="{Binding Name}">
                <controls:DataGridTextColumn.ElementStyle>
                    <Style TargetType="TextBlock">
                        <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
                    </Style>
                </controls:DataGridTextColumn.ElementStyle>
            </controls:DataGridTextColumn>
            <controls:DataGridTextColumn Header="Desc"
                                         MaxWidth="200"
                                         Binding="{Binding Desc}">
                <controls:DataGridTextColumn.ElementStyle>
                    <Style TargetType="TextBlock">
                        <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
                    </Style>
                </controls:DataGridTextColumn.ElementStyle>
            </controls:DataGridTextColumn>
        </controls:DataGrid.Columns>
    </controls:DataGrid>
    
    
    

    Thank you.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.