我正在开发Windows应用商店应用。一个页面包含一个ListView
,StackPanel
有一些TextBlocks
和三个按钮:
我希望只有在选择了它们所属的ListItem
时才能看到这三个按钮。我已经在按钮的Binding
属性上尝试了Visibility
的所有可能安排,但到目前为止还没有任何工作。似乎WinRT应用程序的受约束的绑定类型集阻止我使用已知的解决方案。有什么我可以做的吗?
我目前正试图从ListView
SelectionChanged
事件处理程序中的代码中操作对象的角度来考虑它,但还没有任何结果。
以下是ItemTemplate的XAML:
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel FlowDirection="LeftToRight" Orientation="Horizontal">
<StackPanel Style="{StaticResource SessionBlock}" DoubleTapped="StackPanel_DoubleTapped">
<TextBlock Style="{StaticResource SessionTitle}" Text="{Binding Title}" />
<TextBlock Style="{StaticResource SessionStepCount}">
<Run Text="{Binding StepsCount}" />
<Run Text=" Steps" />
</TextBlock>
</StackPanel>
<Button Content=""
Style="{StaticResource ActionButton}" />
<Button Content=""
Style="{StaticResource ActionButton}" />
<Button Content=""
Style="{StaticResource ActionButton}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
答案 0 :(得分:1)
您可以将TemplatedParent
用于相同的
首先在资源中声明bool到可见性转换器
例如
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
然后在xaml中将以下绑定应用于Visibility,并使用上面声明的转换器
Visibility="{Binding TemplatedParent.IsSelected,RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource BooleanToVisibilityConverter}}"
所以这里的技巧是找到datatemplate的TemplatedParent,它是内容演示者,然后是它的TemplatedParent,它是ListViewItem,IsSelected属性就是你要找的东西
所以你的例子可以如下
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel FlowDirection="LeftToRight" Orientation="Horizontal">
<StackPanel Style="{StaticResource SessionBlock}" DoubleTapped="StackPanel_DoubleTapped">
<TextBlock Style="{StaticResource SessionTitle}" Text="{Binding Title}" />
<TextBlock Style="{StaticResource SessionStepCount}">
<Run Text="{Binding StepsCount}" />
<Run Text=" Steps" />
</TextBlock>
</StackPanel>
<Button Content=""
Style="{StaticResource ActionButton}"
Visibility="{Binding TemplatedParent.IsSelected,RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource BooleanToVisibilityConverter}}" />
<Button Content=""
Style="{StaticResource ActionButton}"
Visibility="{Binding TemplatedParent.IsSelected,RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource BooleanToVisibilityConverter}}" />
<Button Content=""
Style="{StaticResource ActionButton}"
Visibility="{Binding TemplatedParent.IsSelected,RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource BooleanToVisibilityConverter}}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
在上面的示例中,我将相同的内容应用于所有三个按钮,您也可以将它们全部放在堆栈面板中并对其应用单个绑定,从而缩短代码。
答案 1 :(得分:-1)
我从来没有找到过通过XAML做我想做的事情的方法,但我能够用一些代码隐藏来完成它。可悲的是,代码隐藏中的东西真的很模糊,需要一些幸运和勤奋的Google-fu来找到这样做的咒语。真正的归功于此博客页面:http://blogs.msdn.com/b/wpfsdk/archive/2007/04/16/how-do-i-programmatically-interact-with-template-generated-elements-part-ii.aspx
我做的是,我从该博客页面添加了稍微修改过的代码版本:
private List<childItem> findVisualChildren<childItem>(DependencyObject obj) where childItem : DependencyObject {
List<childItem> results = new List<childItem>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) {
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is childItem) {
results.Add((childItem)child);
} else {
results.AddRange(findVisualChildren<childItem>(child));
}
}
return results;
}
它以递归方式搜索可视元素的子元素以查找给定类型的元素,并将它们全部返回到列表中。整洁,但这不是所有看起来像jibber-jabber? Win Forms至少提供了一种与子节点交互的非常明显的方法。
然后,从SelectionChanged
的{{1}}事件处理程序内部调用该方法:
ListView
因此,您可以看到处理程序迭代ListView中的每个项目。对于每一个,它抓住private void SessionsList_SelectionChanged(object sender, SelectionChangedEventArgs e) {
for (int itemIdx = 0; itemIdx < SessionsList.Items.Count; itemIdx++) {
ListViewItem eachItem = (ListViewItem)SessionsList.ContainerFromIndex(itemIdx);
// Content Presenter stuff is from the blog post. I have no idea.
var presenters = findVisualChildren<ContentPresenter>(eachItem);
if (presenters != null && presenters.Count > 0) {
var buttonsList = findVisualChildren<Button>(presenters[0]);
if (buttonsList != null && buttonsList.Count > 0) {
for (int buttonIdx = 0; buttonIdx < buttonsList.Count; buttonIdx++) {
Button eachButton = (Button)buttonsList[buttonIdx];
if (itemIdx == SessionsList.SelectedIndex) {
eachButton.Visibility = Visibility.Visible;
} else {
eachButton.Visibility = Visibility.Collapsed;
}
}
}
}
}
}
无论是什么。然后,它使用该对象上的ContentPresenter
来查找属于它的所有按钮。如果它在当前选定的项目上运行,则按钮可见;否则,它们就会崩溃。
它完全符合我的要求,但我不禁感到失望的是,我找不到正确的约束法术来做'正确的方法'。
我是否正确地认为WinFT版本的WPF严重削弱了绑定能力?它似乎与WPF中可用于我工作的非商店桌面应用程序的内容相差甚远。