x:bind observable collection to Grid column width

BitSmithy 2,161 Reputation points
2025-02-12T11:39:17.0966667+00:00

Hello,

I am trying to x:bind ObservableCollection to Grid columns, but my code works only partly.

I have such XAML:

        <ListView x:Name="lvExpAndCosts" ItemsSource="{x:Bind ocExpendituresAndCosts}">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:FinancialItem">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="{x:Bind Columns[0], Mode=OneWay}"></ColumnDefinition>
                            <ColumnDefinition Width="{Binding Columns[1], Mode=OneWay}"></ColumnDefinition>
                            <ColumnDefinition Width="Auto"></ColumnDefinition>
                            <ColumnDefinition></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <TextBox Text="{x:Bind Name}" Grid.Column="0"
                                 BorderThickness="1"
                                 ></TextBox>
                        <TextBox Text="{x:Bind Amount}" Grid.Column="1"   
                                 TextAlignment="Right"
                                 BorderThickness="1"
                                 ></TextBox>
                            <Button x:Name="btnAddFinancialItem" Content="+" Margin="10,0,0,0" Grid.Column="2"
                                    Click="btnAddFinancialItem_Click"></Button>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

And such code behind:

    private void btnAddFinancialItem_Click(object sender, RoutedEventArgs e)

    {

        if (sender is Button btn && btn.DataContext is FinancialItem fi)

        {

            int rowIndexToAdd = lvExpAndCosts.IndexFromContainer(lvExpAndCosts.ContainerFromItem(fi)) + 1;

            //define default financial item

            fi.Columns.Add(new GridLength(300, GridUnitType.Pixel));

            fi.Columns.Add(new GridLength(100));

            fi.Columns.Add(new GridLength(400));

            FinancialItem fiToAdd = new FinancialItem() { Name = "New expenditure", Amount = 0.00 };

            ocExpendituresAndCosts.Insert(rowIndexToAdd, fiToAdd);

        }

    }

}

public class FinancialItem : INotifyPropertyChanged

{

    public ObservableCollection<GridLength> Columns { get; set; } = new ObservableCollection<GridLength>();

    string name;

    double amount; //+ or -

    public event PropertyChangedEventHandler PropertyChanged;

    public string Name

    {

        get

        {

            return name;

        }

        set

        {

            if (value != name && this.PropertyChanged != null)

            {

                name = value;

                this.PropertyChanged(this, new PropertyChangedEventArgs("Name"));

            }

            else

                name = value;

        }

    }

    public double Amount

    {

        get

        {

            return amount;

        }

        set

        {

            if (value != amount && this.PropertyChanged != null)

            {

                amount = value;

                this.PropertyChanged(this, new PropertyChangedEventArgs("Amount"));

            }

            else

                amount = value;

        }

    }

}
```Now I use + button to add new row to ObservableCollection. Row is added succesfully, but Grid columns have wrong width. When I use x:bind there exception occurs, when I use Binding  data from FinancialItem.Columns arent trasported to Grid columns..
Universal Windows Platform (UWP)
0 comments No comments
{count} votes

Accepted answer
  1. Junjie Zhu - MSFT 20,531 Reputation points Microsoft Vendor
    2025-02-13T06:57:57.4366667+00:00

    Hello @BitSmithy ,

    Welcome to Microsoft Q&A!

    Thank you for providing the complete code. This unexpected behavior has nothing to do with the binding method, you can use x:Bind and Binding. The reason is that Columns is empty and x:bind cannot find the corresponding value in Data context.

    When adding a new FinancialItem, your code only adds fiToAdd, and the other local variable fi does not seem to be used.

    <ListView x:Name="lvExpAndCosts" ItemsSource="{x:Bind ocExpendituresAndCosts}">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:FinancialItem">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="{Binding Columns[0], Mode=OneWay}"></ColumnDefinition>
                        <ColumnDefinition Width="{Binding Columns[1], Mode=OneWay}"></ColumnDefinition>
                        <ColumnDefinition Width="Auto"></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <TextBox Text="{Binding Name}" Grid.Column="0"
                             BorderThickness="1"
                             ></TextBox>
                    <TextBox Text="{Binding Amount}" Grid.Column="1"   
                             TextAlignment="Right"
                             BorderThickness="1"
                             ></TextBox>
                    <Button x:Name="btnAddFinancialItem" Content="+" Margin="10,0,0,0" Grid.Column="2"
                                Click="btnAddFinancialItem_Click"></Button>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    
    
    private void btnAddFinancialItem_Click(object sender, RoutedEventArgs e)
    {
                
        if (sender is Button btn && btn.DataContext is FinancialItem fi)
        {
            int rowIndexToAdd = lvExpAndCosts.IndexFromContainer(lvExpAndCosts.ContainerFromItem(fi)) + 1;
            //define default financial item
            FinancialItem fiToAdd = new FinancialItem() { Name = "Test", Amount = 0 };
            fiToAdd.Columns.Add(new GridLength(100, GridUnitType.Pixel));
            fiToAdd.Columns.Add(new GridLength(100));
            fiToAdd.Columns.Add(new GridLength(100));          
            ocExpendituresAndCosts.Insert(rowIndexToAdd, fiToAdd);
        }
    }
    

    Thank you.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

0 additional answers

Sort by: Most helpful

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.