积极答复者
关于GridView数据分组后快速定位到组的问题

问题
答案
-
没有根据组名直接滚动的,与其自己实现一个,还不如 ScrollIntoView 方法。
其他方法,有通过SctollViewer来滚动的:
ScrollViewer scrollviewer= GetVisualChild<ScrollViewer>(ItemGridView); scrollviewer.ScrollToHorizontalOffset(...); ...... public static T GetVisualChild<T>(DependencyObject parent) where T : DependencyObject { T child = default(T); int numVisuals = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < numVisuals; i++) { DependencyObject d = (DependencyObject)VisualTreeHelper.GetChild(parent, i); child = d as T; if (child == null) child = GetVisualChild<T>(d); if (child != null) break; } return child; }
通过可视树找到GridViewer的ScrollViewer,然后让其滚动。Bob Bao [MSFT]
MSDN Community Support | Feedback to us
- 已标记为答案 edmundzhang 2012年4月19日 6:46
- 取消答案标记 edmundzhang 2012年5月11日 3:52
- 已标记为答案 edmundzhang 2012年5月23日 5:53
全部回复
-
没有根据组名直接滚动的,与其自己实现一个,还不如 ScrollIntoView 方法。
其他方法,有通过SctollViewer来滚动的:
ScrollViewer scrollviewer= GetVisualChild<ScrollViewer>(ItemGridView); scrollviewer.ScrollToHorizontalOffset(...); ...... public static T GetVisualChild<T>(DependencyObject parent) where T : DependencyObject { T child = default(T); int numVisuals = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < numVisuals; i++) { DependencyObject d = (DependencyObject)VisualTreeHelper.GetChild(parent, i); child = d as T; if (child == null) child = GetVisualChild<T>(d); if (child != null) break; } return child; }
通过可视树找到GridViewer的ScrollViewer,然后让其滚动。Bob Bao [MSFT]
MSDN Community Support | Feedback to us
- 已标记为答案 edmundzhang 2012年4月19日 6:46
- 取消答案标记 edmundzhang 2012年5月11日 3:52
- 已标记为答案 edmundzhang 2012年5月23日 5:53
-
你的Items是通过数据邦定的吗? 如果是的话,这个Item不是简单通过GridView.Items[i]来获得的,而是你的邦定的那个具体Item对象,例如你邦定了10个String的了List,给ScrollIntoView方法的Item应该是List[i]里面的某个Item对象。
Bob Bao [MSFT]
MSDN Community Support | Feedback to us
-
用的是item对象,但还不是行,不知道是哪儿的问题,如下:
try
{
Friend friend;//item对象
string GroupName = (ComboBoxGroup.SelectedItem as FriendsGroup).GroupName;for (int i = 0; i < m_FriendsSource.Count; i++) //m_FriendsSource为FriendGridView绑定的数据源,类型为ObservableCollection<GroupInfoList<object>>,它是按组划分的,关键字为GroupName
{
if (m_FriendsSource[i].GroupName.ToString() == GroupName)
{
friend = m_FriendsSource[i][0] as Friend;
FriendGridView.ScrollIntoView(friend);
break;
}
}
}
catch (Exception ex)
{}
public class GroupInfoList<T> : ObservableCollection<object>
{
/// <summary>
/// 组名
/// </summary>
public object GroupName { get; set; }
} -
关于ScrollIntoView()我用了一个ListBox控件来测试,发现也没有起到作用!!
<ListBox x:Name="talkBox" ScrollViewer.HorizontalScrollMode="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" Margin="0" BorderThickness="0"/>
<Button x:Name="btnSend" Content="发送" Click="btnSend_Click"/>string item= "aaaaa"
talkBox.Items.Add(item);
talkBox.ScrollIntoView(item);点击按钮后talkBox总是显示第一项,不会滚动到新加的哪一项。很费解啊!
-
你不要一直往ListBox.Items里面添加一样内容的String, ListBox在Item是内容一样的String的时候是有问题的,它无法判定各个Item分别是谁。
Bob Bao [MSFT]
MSDN Community Support | Feedback to us
- 已编辑 Jie BaoModerator 2012年4月10日 16:05 混淆了,忘了这个是Metro的帖子
-
请检查是否lvTalk.SelectedItem 的值确实存在或者它存在于你的 talkBox.Items 中,类型是否匹配。 因为虚拟化等原因会影响在这个Item还没有显示之前,你无法控制其进入显示区域。
所以我还是建议用可视树找到GridViewer的ScrollViewer,然后让其滚动。 调用
ScrollToHorizontalOffset 或者 ScrollToVerticalOffset
Bob Bao [MSFT]
MSDN Community Support | Feedback to us
-
所以我还是建议用可视树找到GridViewer的ScrollViewer,然后让其滚动。 调用ScrollToHorizontalOffset 或者 ScrollToVerticalOffset
有没有这个方案的例子,不知道如何实现!!!
-
没有根据组名直接滚动的,与其自己实现一个,还不如 ScrollIntoView 方法。
其他方法,有通过SctollViewer来滚动的:
ScrollViewer scrollviewer= GetVisualChild<ScrollViewer>(ItemGridView); scrollviewer.ScrollToHorizontalOffset(...); ...... public static T GetVisualChild<T>(DependencyObject parent) where T : DependencyObject { T child = default(T); int numVisuals = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < numVisuals; i++) { DependencyObject d = (DependencyObject)VisualTreeHelper.GetChild(parent, i); child = d as T; if (child == null) child = GetVisualChild<T>(d); if (child != null) break; } return child; }
通过可视树找到GridViewer的ScrollViewer,然后让其滚动。
Bob Bao [MSFT]
MSDN Community Support | Feedback to us
-
为了检验ScrollIntoView方法,我整理了下代码,代码应该没有什么问题,但就是出现偶尔滚动的现象,您帮着给看看问题是出在哪儿?谢谢!
<Grid Background="{StaticResource FeinnoBackgroundBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="880"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid x:Name="itemDetailGrid" Grid.Column="1" Margin="40,0,100,0">
<Grid.RowDefinitions>
<RowDefinition Height="7*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<ListView x:Name="lvTalk" ScrollViewer.HorizontalScrollMode="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" SelectionMode="None"/>
<StackPanel Grid.Row="1" VerticalAlignment="Bottom">
<TextBox x:Name="txtMessage" Grid.Row="1" Height="100" TextWrapping="Wrap"/>
</StackPanel>
</Grid>
<StackPanel Grid.Row="1" Grid.Column="2" VerticalAlignment="Bottom" Margin="10,0,0,0">
<Button x:Name="btnSend" Content="发送" Click="btnSend_Click"/>
</StackPanel>
</Grid>private void btnSend_Click(object sender, RoutedEventArgs e)
{
try
{
string dd = txtMessage.Text;
lvTalk.Items.Add(dd);
int count = lvTalk.Items.Count - 1;
lvTalk.SelectedIndex = count;
lvTalk.ScrollIntoView(lvTalk.SelectedItem);
}
catch (Exception ex)
{
}
} -
写在Header 中,如下:
public: template<typename T> T GetVisualChild (DependencyObject ^parent) { T child = default(T); int numVisuals = VisualTreeHelper::GetChildrenCount(parent); for(int i=offsetof;i<numVisuals;i++){ DependencyObject ^d = (DependencyObject^) VisualTreeHelper::GetChild(parent,i); child = safe_cast<T>(d); if(child == NULL) child = GetVisualChild<T>(d); else break; } return child; };
Bob Bao [MSFT]
MSDN Community Support | Feedback to us
-
这样就好了:
lvTalk.ItemContainerGenerator.ItemsChanged += ItemContainerGenerator_ItemsChanged; ... void ItemContainerGenerator_ItemsChanged(object sender, ItemsChangedEventArgs e) { int count = lvTalk.Items.Count - 1; lvTalk.SelectedIndex = count; lvTalk.ScrollIntoView(lvTalk.SelectedItem); }
在我们加入一个Item时候这个ItemContainer并没有马上Load好,所以我们这个时候可能无法立刻Scroll到他
Bob Bao [MSFT]
MSDN Community Support | Feedback to us
- 已建议为答案 Jie BaoModerator 2012年4月18日 7:59
-
这样就好了:
lvTalk.ItemContainerGenerator.ItemsChanged += ItemContainerGenerator_ItemsChanged; ... void ItemContainerGenerator_ItemsChanged(object sender, ItemsChangedEventArgs e) { int count = lvTalk.Items.Count - 1; lvTalk.SelectedIndex = count; lvTalk.ScrollIntoView(lvTalk.SelectedItem); }
在我们加入一个Item时候这个ItemContainer并没有马上Load好,所以我们这个时候可能无法立刻Scroll到他
Bob Bao [MSFT]
MSDN Community Support | Feedback to us
-
没有根据组名直接滚动的,与其自己实现一个,还不如 ScrollIntoView 方法。
其他方法,有通过SctollViewer来滚动的:
ScrollViewer scrollviewer= GetVisualChild<ScrollViewer>(ItemGridView); scrollviewer.ScrollToHorizontalOffset(...); ...... public static T GetVisualChild<T>(DependencyObject parent) where T : DependencyObject { T child = default(T); int numVisuals = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < numVisuals; i++) { DependencyObject d = (DependencyObject)VisualTreeHelper.GetChild(parent, i); child = d as T; if (child == null) child = GetVisualChild<T>(d); if (child != null) break; } return child; }
通过可视树找到GridViewer的ScrollViewer,然后让其滚动。
Bob Bao [MSFT]
MSDN Community Support | Feedback to us
这个SctollViewer方法还是不会用,您能不能给个完整点的例子!! -
这个方法是在你的Item加入之后,得到Item的对应ScrollViewer top的位置,然后call scrollviewer.ScrollToHorizontalOffset()到这个位置。 如果你永远是滚动到最低端,你就可以 直接滚动到ScrollViewer的高度位置。
Bob Bao [MSFT]
MSDN Community Support | Feedback to us
-
你好Bob!使用过程中遇到点问题:
1.我将你提供的代码做了如下修改,
public: template<typename T> T GetVisualChild (DependencyObject ^parent) { T child = default(T); int numVisuals = VisualTreeHelper::GetChildrenCount(parent);
//此处已将offsetof改为0;
for(int i=0;i<numVisuals;i++){ DependencyObject ^d = (DependencyObject^) VisualTreeHelper::GetChild(parent,i); child = safe_cast<T>(d);
//此处将NULL改为nullptr
if(child == nullptr) child = GetVisualChild<T>(d); else break; } return child; };
//获得ScrollViewer
ScrollViewer^ scrollviewer= GetVisualChild<ScrollViewer^>(GridView5);
//发生如下编译错误
\readpage.xaml.h(39): error C2882: 'default' : illegal use of namespace identifier in expression
1> readpage.xaml.cpp(98) : see reference to function template instantiation 'T ReadPage::GetVisualChild<Windows::UI::Xaml::Controls::ScrollViewer^>(Windows::UI::Xaml::DependencyObject ^)' being compiled
1> with
1> [
1> T=Windows::UI::Xaml::Controls::ScrollViewer ^
1> ]
1>readpage.xaml.h(39): error C2275: 'T' : illegal use of this type as an expression
1> readpage.xaml.cpp(98) : see declaration of 'T'2.我想给通过ScrollViewer^ scrollviewer= GetVisualChild<ScrollViewer^>(GridView5);得到的scrollviewer
添加一个ViewChanged事件响应函数。
scrollviewer->ViewChanged += ref new EventHandler<ScrollViewerViewChangedEventArgs^>(this,&ReadPage::GridView5_SV_ViewChanged_2);
//Header里的函数声明
void GridView5_SV_ViewChanged_2(Windows::UI::Xaml::Controls::ScrollViewerViewChangedEventArgs^ e);
这样写编译器会提示类型不匹配。请问我该怎么样修改才是正确的呢?谢谢!
补充:
如果我将T child = default(T);改成T child = nullptr;
编译不会出问题,可是link的时候出问题。信息如下,
1>ReadPage.xaml.obj : error LNK2022: metadata operation failed (80131187) : 重复类型中的方法声明不一致(类型: ReadPage;方法: GetVisualChild<Windows::UI::Xaml::Controls::ScrollViewer ^>): (0x06000066)。 1>ReadPage.xaml.obj : error LNK2022: metadata operation failed (801311D6) : 重复类型(ReadPage)中的方法数不同: (0x02000016)。 1>LINK : fatal error LNK1255: link failed because of metadata errors
- 已编辑 frglig 2012年4月25日 8:05 问题更新
-
我是这样做的,在项目中新建一个头文件 VisualTreeHelperEx.h :
#pragma once #include "pch.h" using namespace Windows::UI::Xaml; using namespace Windows::UI::Xaml::Media; template<typename T> T GetVisualChild (DependencyObject ^parent) { T child = nullptr; int numVisuals = VisualTreeHelper::GetChildrenCount(parent); for(int i=0;i<numVisuals;i++){ DependencyObject ^d = (DependencyObject^) VisualTreeHelper::GetChild(parent,i); child = dynamic_cast<T>(d); if(child == nullptr) child = GetVisualChild<T>(d); else break; } return child; };
然后调用就OK, 我测试了 dynamic_cast 是OK的。
Bob Bao [MSFT]
MSDN Community Support | Feedback to us