Search code examples
c#xamlwindows-phone-8.1silverlight-5.0

Binding ColumDefinition Width


I am creating a Windows 8.1 app using https://slideview.codeplex.com in the Windows 10 with help of Visual Studio 2015.

I have added grid to the design with 1 row and two column. In the first page there is big image and no text and in other pages there is icon and text. So I am putting if 4* in first column for first page and 2* in first for second page all works good but I wanted to make it dynamic in ContentPresenter and then I can assign it from C#.

Kindly somebody help me.

I tried in different way like I put below code in SlideApplicationFrame.cs

#region FirstColumnWidth (DependencyProperty)

    /// <summary>
    /// header Image First Column Width
    /// </summary>
    public GridLength FirstColumnWidth
    {
        get { return (GridLength)GetValue(FirstColumnWidthProperty); }
        set { SetValue(FirstColumnWidthProperty, value); }
    }
    public static readonly DependencyProperty FirstColumnWidthProperty =
            DependencyProperty.Register("FirstColumnWidth", typeof(GridLength), typeof(SlideApplicationFrame),
                new PropertyMetadata(new GridLength(4, GridUnitType.Star))); 

    #endregion

    #region ContentFirstColumnWidth (Attached DependencyProperty)

    public static readonly DependencyProperty ContentFirstColumnWidth =
            DependencyProperty.RegisterAttached("ContentFirstColumnWidth", typeof(GridLength), typeof(SlideApplicationFrame), new PropertyMetadata(new GridLength(4, GridUnitType.Star)));

    public static void SetContentFirstColumnWidth(DependencyObject o, GridLength value)
    {
        o.SetValue(ContentFirstColumnWidth, value);
    }

    public static GridLength GetContentFirstColumnWidth(DependencyObject o)
    {
        return (GridLength)o.GetValue(ContentFirstColumnWidth);
    }

    #endregion

Then I use it in my ContentPresenter Like this

<ContentPresenter  library:SlideApplicationFrame.ContentFirstColumnWidth="{TemplateBinding FirstColumnWidth}" Grid.Column="1"/>

and at the end in style setter

<ColumnDefinition Width="{Binding library:SlideApplicationFrame.ContentFirstColumnWidth}"/>

Whole Style Setter is as below

<Setter Property="HeaderTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Grid  x:Name="GridHeader">
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="{Binding library:SlideApplicationFrame.ContentFirstColumnWidth}"/>
                            <ColumnDefinition Width="5*"/>
                        </Grid.ColumnDefinitions>
                    </Grid>
                </DataTemplate>
            </Setter.Value>
        </Setter>

and setting from MainPage.xaml.cs

SlideApplicationFrame RootFrame = Window.Current.Content as SlideApplicationFrame;

RootFrame.FirstColumnWidth = new GridLength(4, GridUnitType.Star);

Please help me I will be highly appreciated


Solution

  • Well first you have to have in mind that the values of ColumnDefinition Width and RowDefinition Height are not of type Double but of type GridLength

    And after that there are two scenarios that I can think of:

    1. Binding to another element's value

    2. Binding to value from the ViewModel or the code behind

    Case 1:

    If You're binding to some value that is double you will need to also use a Converter to convert this value to GridLength

    Case 2:

    If You're binding to something in the code you could create the property of type GridLength and bind directly, or if the value is double again use Converter like in the previous use case.

    Some References on the type

    GridLength Structure

    GridUnitType Enumeration

    • Auto - The size is determined by the size properties of the content object.
    • Pixel - The value is expressed as a pixel.
    • Star - The value is expressed as a weighted proportion of available space.

    Edit - Just a simple example of working binding

    Still didn't manage to find time to recreate your exact situation so I just used GridView (as it has also header) - Content is purple, header consists of two grid columns - green and red, green is bound to dependency property defined in main page

    XAML

    <Page
        ...
        x:Name="root">
        <Page.Resources>
            <Style TargetType="GridView" >
                <Setter Property="HeaderTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <Grid x:Name="GridHeader" Height="200">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="5*"/>
                                    <ColumnDefinition Width="{Binding ElementName=root, Path=TestGridLength}"/>
                                </Grid.ColumnDefinitions>
                                <Grid Background="Red" Grid.Column="0"></Grid>
                                <Grid Background="Green" Grid.Column="1"></Grid>
                            </Grid>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Page.Resources>
    
        <GridView Background="Purple">
        </GridView>
    </Page>
    

    Code behind

    public GridLength TestGridLength
    {
        get { return (GridLength)GetValue(TestGridLengthProperty); }
        set { SetValue(TestGridLengthProperty, value); }
    }
    
    public static readonly DependencyProperty TestGridLengthProperty =
        DependencyProperty.Register(
            "TestGridLength",
            typeof(GridLength),
            typeof(MainPage),
            new PropertyMetadata(null));
    
    
    public MainPage()
    {
        this.InitializeComponent();
        this.TestGridLength = new GridLength(10, GridUnitType.Star);
    }