MasterDetailView UWP - 访问 ListView(或使其滚动)
MasterDetailView UWP - Access the ListView (or make it scroll)
我最近发现了 UWP 社区工具包,我很喜欢它。我现在正在使用 MasterDetailView
,它几乎可以满足我的需要:但它缺少一件重要的事情:我无法访问内部 "ListView".
在我的应用程序中,我有两个按钮:前进和后退,按下它们时我只是在列表中前进和后退。我发现了一个访问 prev/next 元素的技巧,如下所示:
public void GoForward()
{
if (MasterDetailView.Items.Count > 0)
{
bool isNextGood = false;
MyItem selectedItem = MasterDetailView.Items[MasterDetailView.Items.Count - 1] as MyItem;
foreach (var v in MasterDetailView.Items)
{
if (isNextGood)
{
selectedItem = v as MyItem;
break;
}
if (v == MasterDetailView.SelectedItem)
isNextGood = true;
}
MasterDetailView.SelectedItem = selectedItem;
}
}
这只是因为我无法访问 "SelectedIndex" 并且我只有 SelectedItem 可用。现在,显然不是所有项目都可以同时可见,因此 MasterDetailView 提供了一个带有滚动条的横向 ListView。当按下我的 next/prev 按钮时,SelectedItem 会发生变化,但不会在所选元素处滚动:选择变为 forward/back 但列表已锁定。这会产生非常负面的反馈,因为我在列表中的某处丢失了我的选择,我必须搜索它。
我想怎么解决呢?我尝试这种方法:
1) 找到MasterDetailView 的样式。在里面我发现了一个 ListViewStyle,所以我尝试放入一个简单的 "SelectionChanged" 事件并在 App.xaml.cs 处处理它。
<ListView x:Name="MasterList"
Grid.Row="1"
IsTabStop="False"
ItemContainerStyle="{TemplateBinding ItemContainerStyle}"
ItemTemplate="{TemplateBinding ItemTemplate}"
ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}"
ItemsSource="{TemplateBinding ItemsSource}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
SelectionChanged="MasterList_SelectionChanged"/>
CS:
private void MasterList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListView list = sender as ListView;
list.ScrollIntoView(list.SelectedItem);
}
但是,如前所述,"Events cannot be set in the Application class XAML file"。
2)考虑取SelectedItem的parent:我尝试将ListViewItem中的SelectedItem转换,然后访问parent,但第一次转换失败,因为SelectedItem似乎不是ListViewItem,而是"MyItem" 类型。像这样,我无法访问父级。
private void MasterDetailView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var item = MasterDetailView.SelectedItem as ListViewItem;
var parent = item.Parent;
var list = parent as ListView;
}
所以我来了...我不想放弃我对 MasterDetailView 的所有工作以传递给另一个控件。是否有任何简单的方法来访问列表,或者只是在我更改选择时滚动列表?只想做一件事,像这样:
private void List_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListView list = sender as ListView;
list.ScrollIntoView(list.SelectedItem);
}
当发生选择改变时简单地滚动到选择中,但我没有简单的 ListView,而是 MasterDetailView 控件。即使完全在 XAML 中完成:对我来说最重要的是滚动此列表!
谢谢。
解决方案
这个方法太棒了。只需复制粘贴即可。
public static T FindChildOfType<T>(DependencyObject root) where T : class
{
var queue = new Queue<DependencyObject>();
queue.Enqueue(root);
while (queue.Count > 0)
{
DependencyObject current = queue.Dequeue();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(current); i++)
{
var child = VisualTreeHelper.GetChild(current, i);
var typedChild = child as T;
if (typedChild != null)
{
return typedChild;
}
queue.Enqueue(child);
}
}
return null;
}
然后简单地使用它来检索列表并使其滚动。是的宝贝!
private void MasterDetailView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var v = FindChildOfType<ListView>(MasterDetailView);
v.ScrollIntoView(MasterDetailView.SelectedItem);
}
请注意"MasterDerailView"是我元素的x:Name,不是class。
您可以使用 FindChildOfType 实现通过 [=16= 获取 ListView ]VisualTreeHelper,如本答案所示:
我最近发现了 UWP 社区工具包,我很喜欢它。我现在正在使用 MasterDetailView
,它几乎可以满足我的需要:但它缺少一件重要的事情:我无法访问内部 "ListView".
在我的应用程序中,我有两个按钮:前进和后退,按下它们时我只是在列表中前进和后退。我发现了一个访问 prev/next 元素的技巧,如下所示:
public void GoForward()
{
if (MasterDetailView.Items.Count > 0)
{
bool isNextGood = false;
MyItem selectedItem = MasterDetailView.Items[MasterDetailView.Items.Count - 1] as MyItem;
foreach (var v in MasterDetailView.Items)
{
if (isNextGood)
{
selectedItem = v as MyItem;
break;
}
if (v == MasterDetailView.SelectedItem)
isNextGood = true;
}
MasterDetailView.SelectedItem = selectedItem;
}
}
这只是因为我无法访问 "SelectedIndex" 并且我只有 SelectedItem 可用。现在,显然不是所有项目都可以同时可见,因此 MasterDetailView 提供了一个带有滚动条的横向 ListView。当按下我的 next/prev 按钮时,SelectedItem 会发生变化,但不会在所选元素处滚动:选择变为 forward/back 但列表已锁定。这会产生非常负面的反馈,因为我在列表中的某处丢失了我的选择,我必须搜索它。
我想怎么解决呢?我尝试这种方法:
1) 找到MasterDetailView 的样式。在里面我发现了一个 ListViewStyle,所以我尝试放入一个简单的 "SelectionChanged" 事件并在 App.xaml.cs 处处理它。
<ListView x:Name="MasterList"
Grid.Row="1"
IsTabStop="False"
ItemContainerStyle="{TemplateBinding ItemContainerStyle}"
ItemTemplate="{TemplateBinding ItemTemplate}"
ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}"
ItemsSource="{TemplateBinding ItemsSource}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
SelectionChanged="MasterList_SelectionChanged"/>
CS:
private void MasterList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListView list = sender as ListView;
list.ScrollIntoView(list.SelectedItem);
}
但是,如前所述,"Events cannot be set in the Application class XAML file"。
2)考虑取SelectedItem的parent:我尝试将ListViewItem中的SelectedItem转换,然后访问parent,但第一次转换失败,因为SelectedItem似乎不是ListViewItem,而是"MyItem" 类型。像这样,我无法访问父级。
private void MasterDetailView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var item = MasterDetailView.SelectedItem as ListViewItem;
var parent = item.Parent;
var list = parent as ListView;
}
所以我来了...我不想放弃我对 MasterDetailView 的所有工作以传递给另一个控件。是否有任何简单的方法来访问列表,或者只是在我更改选择时滚动列表?只想做一件事,像这样:
private void List_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListView list = sender as ListView;
list.ScrollIntoView(list.SelectedItem);
}
当发生选择改变时简单地滚动到选择中,但我没有简单的 ListView,而是 MasterDetailView 控件。即使完全在 XAML 中完成:对我来说最重要的是滚动此列表!
谢谢。
解决方案
这个方法太棒了。只需复制粘贴即可。
public static T FindChildOfType<T>(DependencyObject root) where T : class
{
var queue = new Queue<DependencyObject>();
queue.Enqueue(root);
while (queue.Count > 0)
{
DependencyObject current = queue.Dequeue();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(current); i++)
{
var child = VisualTreeHelper.GetChild(current, i);
var typedChild = child as T;
if (typedChild != null)
{
return typedChild;
}
queue.Enqueue(child);
}
}
return null;
}
然后简单地使用它来检索列表并使其滚动。是的宝贝!
private void MasterDetailView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var v = FindChildOfType<ListView>(MasterDetailView);
v.ScrollIntoView(MasterDetailView.SelectedItem);
}
请注意"MasterDerailView"是我元素的x:Name,不是class。
您可以使用 FindChildOfType 实现通过 [=16= 获取 ListView ]VisualTreeHelper,如本答案所示: