ScrollViewer ChangeView on SizeChanged
本文关键字:SizeChanged on ChangeView ScrollViewer | 更新日期: 2023-09-27 17:54:29
我有DataTemplate
,我在HubSection中使用:
<DataTemplate x:Name="dataTemplate2">
<Grid x:Name="greedy">
<ScrollViewer x:Name="scroller" SizeChanged="ScrollViewer_SizeChanged" Height="{Binding Height,ElementName=greedy}" >
<ItemsControl x:Name="itemsControl"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource dataTemplateDetails}">
<ItemsControl.ItemContainerTransitions>
<TransitionCollection>
<ReorderThemeTransition />
<NavigationThemeTransition />
</TransitionCollection>
</ItemsControl.ItemContainerTransitions>
</ItemsControl>
</ScrollViewer>
</Grid>
</DataTemplate>
在我的ItemsControl
中,我有可以扩展的项目。我想要实现的是,当项目展开以查看有关该项目的更多详细信息时。我希望Scrollviewer
向下滚动(用于ScrollViewer
的大小更改量(。
SizeChanged
事件的代码隐藏:
private void ScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
{
ScrollViewer myScroll = (ScrollViewer)sender;
myScroll.ChangeView(null, myScroll.ScrollableHeight, null, false);
}
我现在所做的并没有达到我的预期。我现在向下滚动到最后。但问题是,只有当项目扩展了可用视图的大小时,它才会滚动(显示滚动条(。然后,如果我展开另一个项目,它就不起作用了。如果我隐藏项目的详细信息(滚动条也隐藏(并再次展开它,它将再次工作。这就像SizeChanged
事件只发生在ScrollViewer
开始工作时,但高度无限,不会改变。
我尝试过将行设置为"*"的网格,它不会改变任何内容。现在,我尝试通过将其绑定到ItemsControl
的高度来设置高度——仍然是相同的行为。
你能帮我找到解决方案,展示思考的路径,或者给我一些变通方法吗?
编辑:
我准备了一些代码来进行操作,看看到底发生了什么。
1( 创建新项目->应用商店(c#(->Windows Phone 8.1(空白应用程序(并将其命名为"滚动">
2( 将此代码粘贴到MainPage.xaml
<Page
x:Class="scroll.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:scroll"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="DarkOliveGreen">
<Page.Resources>
<DataTemplate x:Name="dataTemplateDetails">
<Grid Name="grido" Grid.Row="1" Margin="10,10,10,10">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="Auto" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="Black" CornerRadius="10" Opacity="0.4" />
<Border Grid.Row="1" Background="Black" CornerRadius="10" Opacity="0.3" />
<Border Grid.Row="2" Background="Black" CornerRadius="10" Opacity="0.2" />
<Border Grid.Row="3" Background="Black" CornerRadius="10" Opacity="0.1" />
<TextBlock Grid.Row="0" Text="{Binding Name}" Style="{StaticResource BaseTextBlockStyle}" HorizontalAlignment="Center"/>
<Grid Grid.Row="1" HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Margin="5,0,5,0" Text="Description:" Style="{StaticResource BaseTextBlockStyle}"/>
<TextBlock Grid.Column="1" Text="{Binding Description}" Style="{StaticResource BaseTextBlockStyle}"/>
</Grid>
<TextBlock Grid.Row="2" Text="Next row" Style="{StaticResource BaseTextBlockStyle}" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="3" Text="Next row" Style="{StaticResource BaseTextBlockStyle}" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
<DataTemplate x:Name="dataTemplate2">
<Grid x:Name="greedy" >
<ScrollViewer x:Name="scroller" SizeChanged="ScrollViewer_SizeChanged" VerticalAlignment="Top">
<ItemsControl x:Name="itemsControl"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource dataTemplateDetails}">
<ItemsControl.ItemContainerTransitions>
<TransitionCollection>
<ReorderThemeTransition />
<NavigationThemeTransition />
</TransitionCollection>
</ItemsControl.ItemContainerTransitions>
</ItemsControl>
</ScrollViewer>
</Grid>
</DataTemplate>
</Page.Resources>
<Page.BottomAppBar>
<CommandBar Background="Black" Opacity="0.6" x:Name="myCommandBar">
<AppBarButton Icon="Add" Label="Add" x:Name="AddItem" Click="Add_Click"/>
<AppBarButton Icon="Delete" Label="Delete" x:Name="RemoveItem" Click="Delete_Click"/>
</CommandBar>
</Page.BottomAppBar>
<Grid>
<Hub x:Name="myHub" Header="Test">
<HubSection x:Uid="myDetailsHubsection" x:Name="myDetailsHubsection" Header="Details" DataContext="{Binding Items}" ContentTemplate="{StaticResource dataTemplate2}" />
</Hub>
</Grid>
3( 将此代码粘贴到MainPage.xaml.cs 中
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace scroll
{
public sealed partial class MainPage : Page
{
public static Details dataContextItems;
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
dataContextItems = new Details();
}
public class TestItem
{
public string Name { get; set; }
public string Description { get; set; }
public TestItem(string n, string d)
{
Name = n;
Description = d;
}
}
public class Details : INotifyPropertyChanged
{
private ObservableCollection<TestItem> _items;
public ObservableCollection<TestItem> Items
{
set
{
_items = value;
NotifyPropertyChanged("Items");
}
get
{
return _items;
}
}
public Details()
{
_items = new ObservableCollection<TestItem>();
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.DataContext = dataContextItems;
}
private void Add_Click(object sender, RoutedEventArgs e)
{
TestItem iAmAnItem = new TestItem("Name of an item", "Long and detailed description of an item");
dataContextItems.Items.Add(iAmAnItem);
}
private void Delete_Click(object sender, RoutedEventArgs e)
{
if (dataContextItems.Items.Count > 0)
dataContextItems.Items.RemoveAt(0);
}
private void ScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
{
ScrollViewer myScroll = (ScrollViewer)sender;
myScroll.ChangeView(null, myScroll.ScrollableHeight, null, false);
}
}
}
4( 运行应用
5( 当你添加前两个项目时,你不能滚动它们,但当你添加更多项目时,当项目"需要更多空间"显示并出现滚动条时,你可以看到它会向下滚动。但是添加更多的项目是行不通的。如果您删除项目并再次添加"第三个"项目,它将向下滚动。
我希望它在每次滚动查看器的大小发生变化时向下滚动(在这种情况下,当出现新项目时,但请记住,当项目在我的原始解决方案中"扩展"时,它应该工作,并且可以同时有几个扩展项目(。
我一直在修改解决方案,终于找到了一种方法。我想问题是我不明白ScrollViewer
是如何工作的。我把滚动高度作为UIElement的高度,希望SizeChanged被解雇,但事实并非如此。ScrollViewer
没有改变它的大小,因为它只占用了它所能占用的全部空间,然后只显示其中有多少内容(就像ScrollViewer
几乎总是无限高,除非它小于实际可用的视图空间(。随着前两个项目的增加,SizeChanged
事件也和第三个项目一起启动,然后什么也没发生。这证明了这一点。
每当ScrollViewer
(或者在这种情况下是Grid
(的大小发生变化时,我都需要激发SizeChanged
。解决方案非常简单,但仍然需要了解ScrollViewer
是如何工作的——现在看来,很明显,它永远不会超过可用空间。
为使其发挥作用所做的更改:
<DataTemplate x:Name="dataTemplate2">
<ScrollViewer x:Name="scroller" VerticalAlignment="Top" HorizontalAlignment="Stretch" IsEnabled="True" >
<Grid VerticalAlignment="Top" x:Name="greedo" SizeChanged="greedo_SizeChanged">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ItemsControl x:Name="itemsControl"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource dataTemplateDetails}">
<ItemsControl.ItemContainerTransitions>
<TransitionCollection>
<ReorderThemeTransition />
<NavigationThemeTransition />
</TransitionCollection>
</ItemsControl.ItemContainerTransitions>
</ItemsControl>
</Grid>
</ScrollViewer>
</DataTemplate>
和代码背后:
private void greedo_SizeChanged(object sender, SizeChangedEventArgs e)
{
Grid takingScroll = (Grid)sender;
ScrollViewer myScroll = (ScrollViewer)takingScroll.Parent;
myScroll.ChangeView(null, myScroll.ScrollableHeight, null, false);
}