locked
XAML Converters: `object value` has wrong value? RRS feed

  • Question

  • I have a GridView and want the GridViewItems to have 50% of the GridView's height. So if the GridView has a height of 768.0, the GridViewItems should be 384.0 high.

    To achieve this, I implemented a converter that passes the ActualHeight of a named element (the GridView) to the converter.

    <GridView x:Name="videoGridView" ItemsSource="{Binding Movies}" ItemContainerStyle="{StaticResource GridViewItemStyle}" RightTapped="videoGridView_RightTapped">
        <GridView.ItemTemplate>
            <DataTemplate>
                <Image Source="{Binding PosterPath}" 
                       Height="{Binding Path=ActualHeight, ConverterParameter=50, 
                       Converter={StaticResource SetPercentageConverter}, 
                       ElementName=videoGridView, Mode=OneWay}" />
            </DataTemplate>
        </GridView.ItemTemplate>
    </GridView>

    public class SetPercentageConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) {
    // Unfortunately, value is always 0.0 :( if ((double)value != 0.0) { return (double)value / 2; } else { return 384.0; } } public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } }

    The problem I am facing is that `value` is always 0.0, even though the ActualHeight of the `videoGridView` is 768.0 when running the app in my simulator and inspecting it in the debugger. Why? What did I wrong?
    Thursday, November 13, 2014 5:00 PM

Answers

  • Height is set to AUTO. It must remain that way.

    You've stumbled onto something that I ran into several months ago.  The compiler treats auto as 0.  There's no way around it.  I tried everything.
    Friday, November 14, 2014 12:03 PM
  • Hi,

    I cannot seem to reproduce your issue. Using the following code the value of the value parameter in the Convert method is only 0 the first time the methods gets called, and this is because the actual height of the GridView is in fact 0 then because no item container has yet been generated:

    public class SetPercentageConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string language)
            {
                // Unfortunately, value is always 0.0 :(
                if ((double)value != 0.0)
                {
                    return (double)value / 2;
                }
                else
                {
                    return 384.0;
                }
    
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string language)
            {
                throw new NotImplementedException();
            }
        }
    
    <GridView x:Name="videoGridView" >
                <GridView.Resources>
                    <local:SetPercentageConverter x:Key="SetPercentageConverter"/>
                </GridView.Resources>
                <GridView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding}" 
                       Height="{Binding Path=ActualHeight, ConverterParameter=50, 
                       Converter={StaticResource SetPercentageConverter}, 
                       ElementName=videoGridView, Mode=OneWay}" />
                    </DataTemplate>
                </GridView.ItemTemplate>
            </GridView>
    public MainPage()
            {
                this.InitializeComponent();
    
                videoGridView.ItemsSource = new List<string> { "a", "b", "c" };
            }
    



    I am on Windows 8.1 and VS 2013.

    What if you bind to the actual GridView itself?:

    public object Convert(object value, Type targetType, object parameter, string language)
            {
                GridView gw = value as GridView;
                double height = gw.ActualHeight;
    
    
                if (height != 0.0)
                {
                    return height / 2;
                }
                else
                {
                    return 384.0;
                }
    
            }
    
     <DataTemplate>
                        <TextBlock Text="{Binding}" 
                       Height="{Binding ElementName=videoGridView, ConverterParameter=50,
                       Converter={StaticResource SetPercentageConverter}}"  />
                    </DataTemplate>


    Please remember to mark helpful posts as answer and/or helpful.

    Saturday, November 15, 2014 12:06 PM

All replies

  • Hi

    I don't see you assign a height for GirdView, the problem might be GirdView height is 0 therefore I don't think you can get any other value except 0. Please give a try by setting height in GirdView.

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Friday, November 14, 2014 5:08 AM
    Moderator
  • Hi,

    As Hez said you may need to set Height value of GridView. Further more to bind the Height of GridView instead of ActualHeight as below:

    <GridView x:Name="videoGridView" Height ="768" ItemsSource="{Binding Movies}" ItemContainerStyle="{StaticResource GridViewItemStyle}" RightTapped="videoGridView_RightTapped">
       
    <GridView.ItemTemplate>
           
    <DataTemplate>
               
    <Image Source="{Binding PosterPath}"
                      
    Height="{Binding Path=Height, ConverterParameter=50,
                       Converter={StaticResource SetPercentageConverter},
                       ElementName=videoGridView, Mode=OneWay}"
    />
           
    </DataTemplate>
       
    </GridView.ItemTemplate>
    </GridView>

    Give it a shot!

    Rosa

    Friday, November 14, 2014 7:33 AM
  • Height is set to AUTO. It must remain that way.

    Friday, November 14, 2014 8:35 AM
  • Height is set to AUTO. It must remain that way.
    Friday, November 14, 2014 8:36 AM
  • Maybe its possible to binding the height var code after the UI has completed rendered. But GridView height is auto, probably cannot help.

    How about binding the height of the GridView container?

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.



    Friday, November 14, 2014 9:06 AM
    Moderator
  • Height is set to AUTO. It must remain that way.

    You've stumbled onto something that I ran into several months ago.  The compiler treats auto as 0.  There's no way around it.  I tried everything.
    Friday, November 14, 2014 12:03 PM
  • Wow, I cannot believe something as simple as height="50%", which has been around in HTML since 1993 (!) is not possible in XAML …
    Saturday, November 15, 2014 11:39 AM
  • Hi,

    I cannot seem to reproduce your issue. Using the following code the value of the value parameter in the Convert method is only 0 the first time the methods gets called, and this is because the actual height of the GridView is in fact 0 then because no item container has yet been generated:

    public class SetPercentageConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string language)
            {
                // Unfortunately, value is always 0.0 :(
                if ((double)value != 0.0)
                {
                    return (double)value / 2;
                }
                else
                {
                    return 384.0;
                }
    
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string language)
            {
                throw new NotImplementedException();
            }
        }
    
    <GridView x:Name="videoGridView" >
                <GridView.Resources>
                    <local:SetPercentageConverter x:Key="SetPercentageConverter"/>
                </GridView.Resources>
                <GridView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding}" 
                       Height="{Binding Path=ActualHeight, ConverterParameter=50, 
                       Converter={StaticResource SetPercentageConverter}, 
                       ElementName=videoGridView, Mode=OneWay}" />
                    </DataTemplate>
                </GridView.ItemTemplate>
            </GridView>
    public MainPage()
            {
                this.InitializeComponent();
    
                videoGridView.ItemsSource = new List<string> { "a", "b", "c" };
            }
    



    I am on Windows 8.1 and VS 2013.

    What if you bind to the actual GridView itself?:

    public object Convert(object value, Type targetType, object parameter, string language)
            {
                GridView gw = value as GridView;
                double height = gw.ActualHeight;
    
    
                if (height != 0.0)
                {
                    return height / 2;
                }
                else
                {
                    return 384.0;
                }
    
            }
    
     <DataTemplate>
                        <TextBlock Text="{Binding}" 
                       Height="{Binding ElementName=videoGridView, ConverterParameter=50,
                       Converter={StaticResource SetPercentageConverter}}"  />
                    </DataTemplate>


    Please remember to mark helpful posts as answer and/or helpful.

    Saturday, November 15, 2014 12:06 PM