Search code examples
c#xamldata-bindinguwpprogrammatically-created

Binding column width programmatically in UWP?


I am trying to create columns that can be resized by the user during runtime just like in excel. However, I am creating fields dynamically and don't know how to bind the programmatically created column's width to the width of my column created in xaml.

Question: How can I bind column width programmatically rather than in the XAML?

cs:

public sealed partial class WepPage : Page
    {
        static int i = 0;
        Grid grid;
       
        
    public WepPage()
    {
        this.InitializeComponent();
   
    }
    private void AddWepButton_Click(object sender, RoutedEventArgs e)
    {
        addWepStack();    
    }
    private void addWepStack()
    {
       
        grid = new Grid();
        grid.Name = ("ItemGrid" + i.ToString()); 
        WepStackPanel.Children.Add(grid);
        //create columns
        ColumnDefinition col0 = new ColumnDefinition();
        ColumnDefinition col1 = new ColumnDefinition();
        ColumnDefinition col2 = new ColumnDefinition();
        ColumnDefinition col3 = new ColumnDefinition();
        ColumnDefinition col4 = new ColumnDefinition();
        ColumnDefinition col5 = new ColumnDefinition();
        // Set the width of each column
       
        //HERE IS WHERE I WANT TO BIND THE COLUMN WIDTH TO THE WIDTH OF THE HEADERS 
        //SO THE USERS CAN CHANGE THE COLUMN WIDTH WHILE THE APPLICATION IS RUNNING.

        // Add columns to grid
        grid.ColumnDefinitions.Add(col0);
        grid.ColumnDefinitions.Add(col1);
        grid.ColumnDefinitions.Add(col2);
        grid.ColumnDefinitions.Add(col3);
        grid.ColumnDefinitions.Add(col4);
        grid.ColumnDefinitions.Add(col5);

        i++;
    }

}

XAML:

<Page NavigationCacheMode="Required"
    x:Class="WASP.WepPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WASP"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">


    <Page.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="PoleDictionary.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Page.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
         <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200" x:Name="WepNumColumn" x:DefaultBindMode="OneWay"/>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
    
    <!-- HERE IS WHERE I ADDED GRID SPLITTERS SO THE USERS CAN EDIT COLUMN WIDTH
    THIS IS WHAT I WANT THE WIDTH OF THE OTHER COLUMNS BOUND TO-->
    
        <controls:GridSplitter Grid.Column="1">
        <controls:GridSplitter.RenderTransform>
            <TranslateTransform X="-8" />
        </controls:GridSplitter.RenderTransform>
        </controls:GridSplitter>
        <controls:GridSplitter Grid.Column="3">
            <controls:GridSplitter.RenderTransform>
                <TranslateTransform X="-8" />
            </controls:GridSplitter.RenderTransform>
        </controls:GridSplitter>
        <controls:GridSplitter Grid.Column="5">
            <controls:GridSplitter.RenderTransform>
                <TranslateTransform X="-8" />
            </controls:GridSplitter.RenderTransform>
        </controls:GridSplitter>
        <controls:GridSplitter Grid.Column="7">
            <controls:GridSplitter.RenderTransform>
                <TranslateTransform X="-8" />
            </controls:GridSplitter.RenderTransform>
        </controls:GridSplitter>

        <Button x:Name="addWepButton" 
                Content="+" 
                FontSize="30"  
                Grid.Column="10"
                Grid.Row="0"
                Click="AddWepButton_Click" />
        <TextBlock Text="WEP #"
                   Grid.Column="0"
                   Grid.Row="0" 
                   Style="{StaticResource WepTextBlock}"/>
        <TextBlock Text="Type"
                   Grid.Column="2"
                   Grid.Row="0" 
                   Style="{StaticResource WepTextBlock}"/>
        <TextBlock Text="Distance"
                   Grid.Column="4"
                   Grid.Row="0"  
                   Style="{StaticResource WepTextBlock}"/>
        <TextBlock Text="Direction"
                   Grid.Column="6"
                   Grid.Row="0"  
                   Style="{StaticResource WepTextBlock}"/>
        <TextBlock Text="Flip"
                   Grid.Column="8"
                   Grid.Row="0"  
                   Style="{StaticResource WepTextBlock}"/>

        <ScrollViewer Grid.Row="1" Grid.ColumnSpan="20">
            <StackPanel x:Name="WepStackPanel">
                
            </StackPanel>
        </ScrollViewer>
    </Grid>
</Page>

Solution

  • How can I bind column width programmatically rather than in the XAML

    You could subscribe the SizeChanged event of each TextBlock without using Binding, when you resize the column, the SizeChanged event will be triggered, then you can change the width the columns you created in code-behind. You can set the ActualWidth of ColumnDefinition you created in xaml to the width of ColumnDefinition you created in code-behind. For example:

    .xaml:

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="200" x:Name="WepNumColumn" x:DefaultBindMode="OneWay"/>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" x:Name="typeColumn"/>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" x:Name="DistanceColumn"/>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" x:Name="DirectionColumn"/>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" x:Name="FlipColumn"/>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
    
            <controls:GridSplitter x:Name="MySplitter" Grid.Column="1">
            <controls:GridSplitter.RenderTransform>
                <TranslateTransform X="-8" />
            </controls:GridSplitter.RenderTransform>
        </controls:GridSplitter>
        <controls:GridSplitter Grid.Column="3">
            <controls:GridSplitter.RenderTransform>
                <TranslateTransform X="-8" />
            </controls:GridSplitter.RenderTransform>
        </controls:GridSplitter>
        <controls:GridSplitter Grid.Column="5">
            <controls:GridSplitter.RenderTransform>
                <TranslateTransform X="-8" />
            </controls:GridSplitter.RenderTransform>
        </controls:GridSplitter>
        <controls:GridSplitter Grid.Column="7">
            <controls:GridSplitter.RenderTransform>
                <TranslateTransform X="-8" />
            </controls:GridSplitter.RenderTransform>
        </controls:GridSplitter>
    
        <Button x:Name="addWepButton" 
                Content="+" 
                FontSize="30"  
                Grid.Column="10"
                Grid.Row="0"
                Click="AddWepButton_Click" />
            <TextBlock Text="WEP #" SizeChanged="WEPTextBlock_SizeChanged"
                   Grid.Column="0"
                   Grid.Row="0" 
                   x:Name="WEPTextBlock" 
                  />
            <TextBlock Text="Type" SizeChanged="WEPTextBlock_SizeChanged"
                   Grid.Column="2" x:Name="TypeTextBlock" 
                   Grid.Row="0" 
                   />
            <TextBlock Text="Distance" SizeChanged="WEPTextBlock_SizeChanged"
                   Grid.Column="4" x:Name="DistanceTextBlock" 
                   Grid.Row="0"  
                  />
            <TextBlock Text="Direction" SizeChanged="WEPTextBlock_SizeChanged"
                   Grid.Column="6" x:Name="DirectionTextBlock" 
                   Grid.Row="0"  
                   />
            <TextBlock Text="Flip" SizeChanged="WEPTextBlock_SizeChanged"
                   Grid.Column="8" x:Name="FlipTextBlock" 
                   Grid.Row="0"  
                   />
    
        <ScrollViewer Grid.Row="1" Grid.ColumnSpan="20">
                <StackPanel x:Name="WepStackPanel">
                </StackPanel>
        </ScrollViewer>
    </Grid>
    

    .cs:

    private void addWepStack()
    {
       ......
        ColumnDefinition col0 = new ColumnDefinition();
        ColumnDefinition col1 = new ColumnDefinition();
        ColumnDefinition col2 = new ColumnDefinition();
        ColumnDefinition col3 = new ColumnDefinition();
        ColumnDefinition col4 = new ColumnDefinition();
            
        // Set the width of each column
        col0.Width = new GridLength(WepNumColumn.ActualWidth);
        col1.Width = new GridLength(typeColumn.ActualWidth);
        col2.Width = new GridLength(DistanceColumn.ActualWidth);
        col3.Width = new GridLength(DirectionColumn.ActualWidth);
        col4.Width = new GridLength(FlipColumn.ActualWidth);
        ......
    }
    
    
    private void WEPTextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (grid != null)
        {
            grid.ColumnDefinitions[0].Width = new GridLength(WepNumColumn.ActualWidth);
            grid.ColumnDefinitions[1].Width = new GridLength(typeColumn.ActualWidth);
            grid.ColumnDefinitions[2].Width = new GridLength(DistanceColumn.ActualWidth);
            grid.ColumnDefinitions[3].Width = new GridLength(DirectionColumn.ActualWidth);
            grid.ColumnDefinitions[4].Width = new GridLength(FlipColumn.ActualWidth);
        }
    }
    

    In addition, the DataGrid XAML control can resize columns during runtime, you can use it directly to create a table format.