问题
I have a flipview which contains photos and descriptions. I want when photo1 be tapped, then descbox1 not visible. And if photo1 be tapped again, then descbox1 will appear.
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>
I tried using the code below:
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;
}
}
But when I tap photo1, descBox1 would not collapse, hiddenBtn would not collapsed, detailBtn would not visible. How to handle it?
回答1:
According to your requirement, I'd think using Binding
here to control these control's visibility would be a simpler solution. For example, we can take advantage of the 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.
Here we can use this property to store the Visibility
and in other controls, bind ther Visibility
property to this property like:
<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>
Then in photo_Tapped
method, we can change Tag
's value to control the visibility of "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" is similar, we only need to set the Mode
of the Binding
to TwoMay
, so that when we change its visibility, "descBox1" and "detailBtn" will also change their visibility automatically.
<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" is the same as "hiddenBtn", but its visibility is opposite to "hiddenBtn". So we will need a InvertedVisibilityConverter
like following:
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;
}
}
}
And in "detailBtn", setting Binding
like following:
<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);
}
Update: To make the visibilities in all FlipViewItem
s have the same behavior, we need a dependence property that can store the visibility "globally". So we can use FlipView
's Tag
property instead of Image
's Tag
property and in Image
set the Binding
like following:
<Image x:Name="photo1"
Margin="0,0,10,10"
Source="{Binding ImagePath}"
Tag="{Binding Tag, ElementName=narrowFlipview, Mode=TwoWay}"
Tapped="photo_Tapped" />
After this all Image
's Tag
will have the same value. And as this is a two-way binding, when we change one Image
's Tag
value, it will automatically change FlipView.Tag
's value and then propagate to all other Images
.
In other controls like "descBox1", "hiddenBtn" and "detailBtn", we can also change their Binding
by change ElementName
from photo1
to narrowFlipview
. Using "detailBtn" for example:
<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>
And there is no need to change the code-behind, after editing the Binding
s in XAML, it should be able to achieve what you want.
来源:https://stackoverflow.com/questions/40231428/photo-and-description-on-flipview