Search code examples
c#uwpwin-universal-appwinrt-xamlmytoolkit

How To Modify Grid Column Width Using Visual State in UWP?


For showing results, I am using Data Grid of MyToolKit Package by following below mentioned example: https://github.com/MyToolkit/MyToolkit/wiki/DataGrid

Using this Grid I am able to show the results. In Order to make grid Responsive I want to set two different Column widths. One is for Narrow State and another one is for Wide State. Here I am adding my grid and visual state code

<controls:DataGrid.Columns>
    <controls:DataGridTextColumn Binding="{Binding billId}" d:DataContext="{d:DesignInstance Type=models:PendingBillDetail}" x:Name="colBillId" >
        <controls:DataGridTextColumn.Header>
            <TextBlock Name="txtBillId" Text="BillId" Foreground="Green" />
        </controls:DataGridTextColumn.Header>
    </controls:DataGridTextColumn>
</controls:DataGrid.Columns>

visual state code

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup>
        <VisualState x:Name="wideView">
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="641" />
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="colBillId.Width" Value="200" />
                <Setter Target="svPendingBillsList.VerticalScrollBarVisibility" Value="Disabled" />
            </VisualState.Setters>
        </VisualState>
        <VisualState x:Name="narrowView">
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="0" />
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="colBillId.Width" Value="10" />
                <Setter Target="svPendingBillsList.HorizontalScrollBarVisibility" Value="Auto" />
                <Setter Target="svPendingBillsList.VerticalScrollBarVisibility" Value="Disabled" />
            </VisualState.Setters>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

Values are not effecting according to the state. Please give me your suggestions to solve this issue.


Solution

  • I think Visual State can't work with your case. In your code, you used colBillId.Width in VisualState.Setters to change the column's width. But after your DataGrid loaded, there is no control in the Visual Tree named colBillId. You can find this in Visual Studio's Live Visual Tree:

    enter image description here

    For each DataGridTextColumn, it's a ContentPresenter that contains the TextBlock you've set in DataGridTextColumn.Header. And as you can see, they are not named. If we want the Setter in VisualState.Setters to work after the page displayed, we must have the named control in visual tree. As a test, we can use following code in Visual State:

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState x:Name="wideView">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="641" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="colBillId.Width" Value="200" />
                    <Setter Target="txtBillId.Foreground" Value="Red" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="narrowView">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="0" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="colBillId.Width" Value="50" />
                    <Setter Target="txtBillId.Foreground" Value="Green" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    

    You will find "BillId" become red if the page's width larger than "641". However the column's width doesn't change. So in your case, Visual State can't work.

    As Mirko Bellabarba said, I'd suggest you use Star (*) sizing in Width as a workaround. For example:

    <controls:DataGrid.Columns>
        <controls:DataGridTextColumn Width="*" Binding="{Binding billId}" d:DataContext="{d:DesignInstance Type=models:PendingBillDetail}">
            <controls:DataGridTextColumn.Header>
                <TextBlock Name="txtBillId" Foreground="Green" Text="BillId" />
            </controls:DataGridTextColumn.Header>
        </controls:DataGridTextColumn>
        <controls:DataGridTextColumn Width="2*" Binding="{Binding billId}" d:DataContext="{d:DesignInstance Type=models:PendingBillDetail}">
            <controls:DataGridTextColumn.Header>
                <TextBlock Foreground="Green" Text="BillId" />
            </controls:DataGridTextColumn.Header>
        </controls:DataGridTextColumn>
    </controls:DataGrid.Columns>