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"类似,我们只需要将Binding
的Mode
设置为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"。所以我们可以使用 FlipView
的 Tag
属性 而不是 Image
的 Tag
属性 并在 Image
中设置 Binding
如下所示:
<Image x:Name="photo1"
Margin="0,0,10,10"
Source="{Binding ImagePath}"
Tag="{Binding Tag, ElementName=narrowFlipview, Mode=TwoWay}"
Tapped="photo_Tapped" />
之后所有 Image
的 Tag
将具有相同的值。由于这是双向绑定,当我们更改一个 Image
的 Tag
值时,它会自动更改 FlipView.Tag
的值,然后传播到所有其他 Images
].
在"descBox1"、"hiddenBtn"和"detailBtn"等其他控件中,我们也可以通过将photo1
更改为ElementName
来更改它们的Binding
到 narrowFlipview
。使用 "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
后,应该可以实现您想要的。
我有一个包含照片和描述的翻转视图。我希望当 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"类似,我们只需要将Binding
的Mode
设置为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"。所以我们可以使用 FlipView
的 Tag
属性 而不是 Image
的 Tag
属性 并在 Image
中设置 Binding
如下所示:
<Image x:Name="photo1"
Margin="0,0,10,10"
Source="{Binding ImagePath}"
Tag="{Binding Tag, ElementName=narrowFlipview, Mode=TwoWay}"
Tapped="photo_Tapped" />
之后所有 Image
的 Tag
将具有相同的值。由于这是双向绑定,当我们更改一个 Image
的 Tag
值时,它会自动更改 FlipView.Tag
的值,然后传播到所有其他 Images
].
在"descBox1"、"hiddenBtn"和"detailBtn"等其他控件中,我们也可以通过将photo1
更改为ElementName
来更改它们的Binding
到 narrowFlipview
。使用 "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
后,应该可以实现您想要的。