Flipview 上的照片和描述

Photo and description on Flipview

我有一个包含照片和描述的翻转视图。我希望当 photo1 被点击时,descbox1 不可见。如果再次点击 photo1,则会出现 descbox1。

XAML:

<FlipView x:Name="narrowFlipview"
          ItemsSource="{Binding Group.Items}"
          SelectedItem="{Binding Item, Mode=TwoWay}"
          Foreground="{x:Null}"
          Visibility="Collapsed">
    <FlipView.ItemTemplate>
        <DataTemplate>
            <Grid x:Name="content1"
                  Margin="0,0,0,0">
                <Image x:Name="photo1"
                       Margin="0,0,10,10"
                       Source="{Binding ImagePath}"
                       Tapped="photo_Tapped" />
                <Grid x:Name="detail"
                      VerticalAlignment="Bottom"
                      Height="200">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="auto" />
                        <RowDefinition Height="auto" />
                    </Grid.RowDefinitions>
                    <Button x:Name="hideBtn"
                            Height="50"
                            Width="50"
                            Margin="0,0,5,0"
                            HorizontalAlignment="Right"
                            VerticalAlignment="Bottom"
                            Grid.Row="0"
                            Click="hideBtn_Click">
                        <Button.Background>
                            <ImageBrush Stretch="Uniform"
                                        ImageSource="images/media/ikon-56-app-white-down.png" />
                        </Button.Background>
                    </Button>
                    <Button x:Name="detailBtn"
                            Height="50"
                            Width="50"
                            Margin="0,0,5,0"
                            HorizontalAlignment="Right"
                            VerticalContentAlignment="Bottom"
                            Grid.Row="1"
                            Visibility="Collapsed"
                            Click="detailBtn_Click">
                        <Button.Background>
                            <ImageBrush Stretch="Uniform"
                                        ImageSource="images/media/ikon-56-app-white-up.png" />
                        </Button.Background>
                    </Button>
                    <ScrollViewer x:Name="descBox1"
                                  Grid.Row="1"
                                  Height="150"
                                  Background="#95000000"
                                  VerticalScrollBarVisibility="Auto">
                        <TextBlock x:Name="descriptionText1"
                                   Text="{Binding Description}"
                                   Margin="20,20,20,0"
                                   TextWrapping="Wrap"
                                   TextAlignment="Justify"
                                   VerticalAlignment="Top"
                                   Height="auto"
                                   Foreground="White"
                                   FontSize="21" />
                    </ScrollViewer>
                </Grid>
            </Grid>
        </DataTemplate>
    </FlipView.ItemTemplate>
</FlipView>

我尝试使用下面的代码:

private DependencyObject FindChildControl<T>(DependencyObject control, string ctrlName)
        {
            int childNumber = VisualTreeHelper.GetChildrenCount(control);
            for (int i = 0; i < childNumber; i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(control, i);
                FrameworkElement fe = child as FrameworkElement;
                // Not a framework element or is null
                if (fe == null) return null;

                if (child is T && fe.Name == ctrlName)
                {
                    // Found the control so return
                    return child;
                }
                else
                {
                    // Not found it - search children
                    DependencyObject nextLevel = FindChildControl<T>(child, ctrlName);
                    if (nextLevel != null)
                        return nextLevel;
                }
            }
            return null;
        }
    public bool _IsOn;
    public bool IsOn
    {
        get
        {
            return _IsOn;
        }
        set
        {
            _IsOn = value;
        }
    }
    private void photo_Tapped(object sender, TappedRoutedEventArgs e)
    {
ScrollViewer descBox1 = FindChildControl<ScrollViewer>(this, "descBox1") as ScrollViewer;
Button hideBtn = FindChildControl<Button>(this, "hideBtn") as Button;
Button detailBtn = FindChildControl<Button>(this, "detaiBtn") as Button;
        IsOn = !IsOn;
        if (_IsOn)
        {
            descBox1.Visibility = Visibility.Collapsed;
            hideBtn.Visibility = Visibility.Collapsed;
            detailBtn.Visibility = Visibility.Visible;
        }
        else
        {
            descBox1.Visibility = Visibility.Visible;
            hideBtn.Visibility = Visibility.Visible;
            detailBtn.Visibility = Visibility.Collapsed;
        }
    }

但是当我点击photo1时,descBox1不会折叠,hiddenBtn不会折叠,detailBtn不可见。 如何处理?

根据您的要求,我认为在这里使用Binding来控制这些控件的可见性将是一个更简单的解决方案。例如,我们可以利用Tag property

Ref Remarks in FrameworkElement.Tag property:

The scenario for the Tag property is to provide an general-purpose property on all FrameworkElement classes that supports data binding, animation and styles for itself but where the property's value does not have any implicit meaning to platform subsystems like layout, app model, text, input and so on.

在这里我们可以使用这个 属性 来存储 Visibility 并且在其他控件中,将 Visibility 属性 绑定到这个 属性 就像:

<ScrollViewer x:Name="descBox1"
              Grid.Row="1"
              Height="150"
              Background="#95000000"
              VerticalScrollBarVisibility="Auto"
              Visibility="{Binding Tag, ElementName=photo1}">
    <TextBlock x:Name="descriptionText1"
               Height="auto"
               Margin="20,20,20,0"
               VerticalAlignment="Top"
               FontSize="21"
               Foreground="White"
               Text="{Binding Description}"
               TextAlignment="Justify"
               TextWrapping="Wrap" />
</ScrollViewer>

然后在photo_Tapped方法中,我们可以改变Tag的值来控制"descBox1".

的可见性
private void photo_Tapped(object sender, TappedRoutedEventArgs e)
{
    var tag = (sender as Image)?.Tag?.ToString();
    //if we didn't set Tag in Image, its value should be null and descBox1 will be Visible 
    if (string.IsNullOrEmpty(tag) || tag.Equals("Visible"))
    {
        (sender as Image).Tag = Visibility.Collapsed;
    }
    else
    {
        (sender as Image).Tag = Visibility.Visible;
    }
}

"hiddenBtn"类似,我们只需要将BindingMode设置为TwoMay,这样当我们改变它的可见性时,"descBox1" 和 "detailBtn" 也会自动更改它们的可见性。

<Button x:Name="hideBtn"
        Grid.Row="0"
        Width="50"
        Height="50"
        Margin="0,0,5,0"
        HorizontalAlignment="Right"
        VerticalAlignment="Bottom"
        Click="hideBtn_Click"
        Visibility="{Binding Tag, ElementName=photo1, Mode=TwoWay}">
    <Button.Background>
        <ImageBrush ImageSource="images/media/ikon-56-app-white-down.png" Stretch="Uniform" />
    </Button.Background>
</Button>

private void hideBtn_Click(object sender, RoutedEventArgs e)
{
    ChangeButtonVisibility(sender);
}

private void ChangeButtonVisibility(object sender)
{
    var visibility = (sender as Button)?.Visibility;
    if (visibility.Equals(Visibility.Visible))
    {
        (sender as Button).Visibility = Visibility.Collapsed;
    }
    else
    {
        (sender as Button).Visibility = Visibility.Visible;
    }
}

"detailBtn"与"hiddenBtn"相同,但可见性与"hiddenBtn"相反。所以我们需要一个像下面这样的 InvertedVisibilityConverter

public class InvertedVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return InvertedVisibility(value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return InvertedVisibility(value);
    }

    private object InvertedVisibility(object value)
    {
        var visibility = value?.ToString();
        if (string.IsNullOrEmpty(visibility) || visibility.Equals("Visible"))
        {
            return Visibility.Collapsed;
        }
        else
        {
            return Visibility.Visible;
        }
    }
}

并且在 "detailBtn" 中,设置 Binding 如下:

<Button x:Name="detailBtn"
        Grid.Row="1"
        Width="50"
        Height="50"
        Margin="0,0,5,0"
        HorizontalAlignment="Right"
        VerticalContentAlignment="Bottom"
        Click="detailBtn_Click"
        Visibility="{Binding Tag, ElementName=photo1, Mode=TwoWay, Converter={StaticResource InvertedVisibilityConverter}}">
    <Button.Background>
        <ImageBrush ImageSource="images/media/ikon-56-app-white-up.png" Stretch="Uniform" />
    </Button.Background>
</Button>

private void detailBtn_Click(object sender, RoutedEventArgs e)
{
    ChangeButtonVisibility(sender);
}

更新: 为了使所有 FlipViewItem 中的可见性具有相同的行为,我们需要一个可以存储可见性的依赖项 属性 "globally"。所以我们可以使用 FlipViewTag 属性 而不是 ImageTag 属性 并在 Image 中设置 Binding 如下所示:

<Image x:Name="photo1"
       Margin="0,0,10,10"
       Source="{Binding ImagePath}"
       Tag="{Binding Tag, ElementName=narrowFlipview, Mode=TwoWay}"
       Tapped="photo_Tapped" />

之后所有 ImageTag 将具有相同的值。由于这是双向绑定,当我们更改一个 ImageTag 值时,它会自动更改 FlipView.Tag 的值,然后传播到所有其他 Images ].

在"descBox1"、"hiddenBtn"和"detailBtn"等其他控件中,我们也可以通过将photo1更改为ElementName来更改它们的BindingnarrowFlipview。使用 "detailBtn" 例如:

<Button x:Name="detailBtn"
        Grid.Row="1"
        Width="50"
        Height="50"
        Margin="0,0,5,0"
        HorizontalAlignment="Right"
        VerticalContentAlignment="Bottom"
        Click="detailBtn_Click"
        Visibility="{Binding Tag, ElementName=narrowFlipview, Mode=TwoWay, Converter={StaticResource InvertedVisibilityConverter}}">
    <Button.Background>
        <ImageBrush ImageSource="images/media/ikon-56-app-white-up.png" Stretch="Uniform" />
    </Button.Background>
</Button>

并且无需更改代码隐藏,编辑XAML中的Binding后,应该可以实现您想要的。