Rose Rose - 11 days ago 4
C# Question

flipview on windows phone 8.1 error "The name '' does not exist in the current context"

I have a flipview containing photo, descbox, detailBtn, hideBtn. I would like if the photo tapped, then descbox and hideBtn appear, while detailBtn not appear. And if the photo tapped again, then descbox and hideBtn not appear, while detailBtn looks.
Or if detailBtn clicked, then descbox and hideBtn appear, while detailBtn not appear. And if hideBtn clicked, then descbox and hideBtn not appear, while detailBtn appear.

I'm using the code below:

private async void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
var item = await NatureDataSource.GetItemAsync((String)e.NavigationParameter);
var group = await NatureDataSource.GetGroupByItemAsync(item);
this.DefaultViewModel["Group"] = group;
this.DefaultViewModel["Item"] = item;
}

public bool _IsOn;
public bool IsOn
{
get
{
return _IsOn;
}
set
{
_IsOn = value;
}
}

private void photo_Tapped(object sender, TappedRoutedEventArgs e)
{
IsOn = !IsOn;
if (!IsOn)
{
descbox.Visibility = Visibility.Collapsed;
detailBtn.Visibility = Visibility.Visible;
hideBtn.Visibility = Visibility.Collapsed;
}
else
{
descbox.Visibility = Visibility.Visible;
detailBtn.Visibility = Visibility.Collapsed;
hideBtn.Visibility = Visibility.Visible;
}
}

private void detailBtn_Tapped(object sender, TappedRoutedEventArgs e)
{
descbox.Visibility = Visibility.Visible;
detailBtn.Visibility = Visibility.Collapsed;
hideBtn.Visibility = Visibility.Visible;
}


but an error message like the following:
error message

XAML:

<FlipView x:Name="narrowFlipview" Grid.Row="1" ItemsSource="{Binding Group.Items}" SelectedItem="{Binding Item, Mode=TwoWay}" Foreground="{x:Null}">
<FlipView.ItemTemplate>
<DataTemplate>
<Grid x:Name="ContentRoot">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EdgeUIThemeTransition Edge="Left"/>
</TransitionCollection>
</Grid.ChildrenTransitions>
<ScrollViewer x:Name="myScroll" VerticalScrollBarVisibility="Auto" Margin="0,0,0,0" VerticalScrollMode="Auto" HorizontalScrollBarVisibility="Auto" ZoomMode="Enabled" MinZoomFactor="1" HorizontalScrollMode="Auto">
<StackPanel Height="325" Width="558">
<Image x:Name="photo" Source="{Binding ImagePath}" Stretch="Uniform" Height="320" Tapped="photo_Tapped" Margin="0,0,0.333,0" />
<Border x:Name="descbox" Background="#A52C2C2C" Height="120" VerticalAlignment="Bottom" Visibility="Collapsed" Margin="0,-120,0,0">
<ScrollViewer VerticalScrollMode="Auto" Height="auto" HorizontalScrollBarVisibility="Visible">
<StackPanel Width="538">
<TextBlock x:Name="desc" Text="{Binding Description}" FontFamily="verdana" FontSize="17" Foreground="#CCFFFFFF" TextWrapping="Wrap" Padding="0,10" TextAlignment="Justify" Height="auto"/>
</StackPanel>
</ScrollViewer>
</Border>
<Image x:Name="detailBtn" Source="images/media/arrow_up.png" Margin="0,-40,0,0" Height="40" Width="40" HorizontalAlignment="Right" Tapped="detailBtn_Tapped"/>
<Image x:Name="hideBtn" Source="images/media/arrow_down.png" Margin="0,-285,0,0" Height="40" Width="40" HorizontalAlignment="Right" Visibility="Collapsed" Tapped="hideBtn_Tapped"/>
</StackPanel>
</ScrollViewer>
</Grid>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>


How to handle it?

Note:
I tried to use the way in Photo and description on Flipview, but on windows phone 8.1 can not be used

Answer

You get the error "descbox" and others don't exist in the current context because they are names of UIElements part of a dataTemplate. The dataTemplate would load only during runtime. The target you want to achieve can be achieved with Data Binding and MVVM concepts far less complexly.

I've created a solution for you based on the data you had provided in the question using Data Binding. I've skipped out the MVVM portion as that is vast enough for an answer. So getting started...

The Updated XAML

based on your code project a few things you could change by putting in the DataBinding for the buttons. like below:

<FlipView x:Name="narrowFlipview" Grid.Row="1" ItemsSource="{Binding Group.Items}" SelectedItem="{Binding Item, Mode=TwoWay}"  Foreground="{x:Null}">
        <FlipView.ItemTemplate>
            <DataTemplate>
                <Grid x:Name="ContentRoot">
                    <Grid.ChildrenTransitions>
                        <TransitionCollection>
                            <EdgeUIThemeTransition Edge="Left"/>
                        </TransitionCollection>
                    </Grid.ChildrenTransitions>
                    <ScrollViewer x:Name="myScroll" VerticalScrollBarVisibility="Auto" Margin="0,0,0,0" VerticalScrollMode="Auto" HorizontalScrollBarVisibility="Auto" ZoomMode="Enabled" MinZoomFactor="1" HorizontalScrollMode="Auto">
                        <StackPanel Height="325" Width="558">
                            <Image x:Name="photo" Source="{Binding ImagePath}" Stretch="Uniform" Height="320" Tapped="photo_Tapped" Margin="0,0,0.333,0" />
                            <Border x:Name="descbox" Background="#A52C2C2C" Height="120" VerticalAlignment="Bottom" Visibility="{Binding IsDescriptionVisible,Converter={StaticResource boolToVisibilityConverter}}" Margin="0,-120,0,0">
                                <ScrollViewer VerticalScrollMode="Auto" Height="auto" HorizontalScrollBarVisibility="Visible">
                                    <StackPanel Width="538">
                                        <TextBlock x:Name="desc" Text="{Binding Description}"  FontFamily="verdana" FontSize="17" Foreground="#CCFFFFFF" TextWrapping="Wrap" Padding="0,10" TextAlignment="Justify" Height="auto"/>
                                    </StackPanel>
                                </ScrollViewer>
                            </Border>
                            <AppBarButton x:Name="detailBtn" Icon="Upload" Margin="0,-40,0,0" Height="40" Width="40" HorizontalAlignment="Right" Visibility="{Binding IsDescriptionVisible,Converter={StaticResource boolToInverseVisibilityConverter}}" Click="DetailsBtn_Click"/>
                            <AppBarButton x:Name="hideBtn" Icon="Download"  Margin="0,-285,0,0" Height="40" Width="40" HorizontalAlignment="Right" Visibility="{Binding IsDescriptionVisible,Converter={StaticResource boolToVisibilityConverter}}" Click="HideBtn_Click"/>
                        </StackPanel>
                    </ScrollViewer>
                </Grid>
            </DataTemplate>
        </FlipView.ItemTemplate>
    </FlipView>

Note: There are UI fails as the margins are not correct but then that's your code. Try not using Margins for an adaptable layout. you could refer my answer here for more details.

The Code Behind for the same:

I've changed the what to do when the Tapped Event is fired. I've left your code commented for reference reasons. The changes in the Code are as below:

    private void photo_Tapped(object sender, TappedRoutedEventArgs e)
    {
        var currentItem = narrowFlipview.SelectedItem as WaterfallDataItem;
        currentItem.IsDataVisible = !currentItem.IsDataVisible;
        //IsOn = !IsOn;
        //if (!IsOn)
        //{
        //    descbox.Visibility = Visibility.Collapsed;
        //    detailBtn.Visibility = Visibility.Visible;
        //    hideBtn.Visibility = Visibility.Collapsed;
        //}
        //else
        //{
        //    descbox.Visibility = Visibility.Visible;
        //    detailBtn.Visibility = Visibility.Collapsed;
        //    hideBtn.Visibility = Visibility.Visible;
        //}
    }



    private void DetailsBtn_Click(object sender, RoutedEventArgs e)
    {
        var currentItem = narrowFlipview.SelectedItem as WaterfallDataItem;
        currentItem.IsDescriptionVisible = true;
    }

    private void HideBtn_Click(object sender, RoutedEventArgs e)
    {
        var currentItem = narrowFlipview.SelectedItem as WaterfallDataItem;
        currentItem.IsDescriptionVisible = false;
    }

The WaterfallDataItem Class Changes:

I've added the Interface INotifyPropertyChanged and added two new properties IsDataVisible and IsDescriptionVisible which raise the PropertyChanged event incase they are changed.

 public class WaterfallDataItem:INotifyPropertyChanged
{
    public WaterfallDataItem(String uniqueId, String title, String imagePath, String description, String content)
    {
        this.UniqueId = uniqueId;
        this.Title = title;
        this.Description = description;
        this.ImagePath = imagePath;
        this.Content = content;
    }

    public string UniqueId { get; private set; }
    public string Title { get; private set; }
    public string Description { get; private set; }
    public string ImagePath { get; private set; }
    public string Content { get; private set; }

    //for the image tap to show description functionality
    private bool isDataVisible;
    public bool IsDataVisible
    {
        get { return isDataVisible; }
        set
        {
            isDataVisible = value;
            if (value)
                IsDescriptionVisible = true;
            RaisePropertyChanged("IsDataVisible");
        }
    }

    //for hide and show the details pannel and hide and show content based on that
    private bool isDescriptionVisible;
    public bool IsDescriptionVisible
    {
        get { return isDescriptionVisible; }
        set { isDescriptionVisible = value; RaisePropertyChanged("IsDescriptionVisible"); }
    }

    //raises the event to the view if any of these properties change
    public event PropertyChangedEventHandler PropertyChanged;
    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public override string ToString()
    {
        return this.Title;
    }
}

Please Note: The PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); Only works with C# 6.0 which is available in Visual Studio 2015. For any editions you will have to use

if (PropertyChanged != null)
{
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

as the new Null Condition operator is only available in C# 6.0. For more information on What's new in c# 6.0 please refer this

The Converter:

The Converter is used to convert the true or false value from the properties to visibility

 public class boolToVisibilityConverter : IValueConverter
{
    public bool isInverseReq { get; set; }
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        bool val = (bool)value;
        if(isInverseReq)
        {
            if (val)
                return Visibility.Collapsed;
            else
                return Visibility.Visible;
        }
        else
        {
            if (val)
                return Visibility.Visible;
            else
                return Visibility.Collapsed;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

The App.xaml

Finally to make the converter work we need to add the converter to the app.xaml. Modify the Application.Resources like below:

<Application.Resources>
    <local:boolToVisibilityConverter x:Key="boolToVisibilityConverter" isInverseReq="False"/>
    <local:boolToVisibilityConverter x:Key="boolToInverseVisibilityConverter" isInverseReq="True"/>
</Application.Resources>

Please note all the classes are simply made in the main project no sub folders, So if you place the classes and converters in some different namespace, do remember to update the xmlns: tag on the xaml

Edit: To Make your solution work:

At the bare minimum you could change a few things in your code to make it work, I have made the changes in the answer. The above changes would let you implement the functionality without changing your code very much. Do let me know if there is anything I missed.

Comments