我已经看到了一些关于WP8或其他的答案,但似乎WP8.1中没有触发器(或者我错过了什么?)
我有一个从代码绑定的datatemplate(它是一个hub datatemplate,我有混合的静态和动态hubsections,因此需要从代码中设置此datatemplate。)
此datatemplate在单独的xaml文件中定义,它包含一个列表框(或listview),其中包含为项目定义的另一个datatemplate。
我需要在项目的tap或listbox selectionchanged上绑定命令(或等效的东西)。但是,模板中定义的tap事件未被调用,因此我想到在UI元素上绑定命令,但这些似乎不支持Commands和交互触发器。
有关如何处理的任何线索? :)
在下面的示例中,我没有得到事件Item_Tapped和ListBox_SelectionChanged,我反正希望将其中一个绑定到viewmodel中的命令。
<DataTemplate x:Key="HubSectionTemplate">
<Grid>
<ListBox ItemsSource="{Binding MyNodes}"
SelectionChanged="ListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="64" Tapped="Item_Tapped" >
<TextBlock Text="{Binding MyText}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</DataTemplate>
这是从代码中使用它的方式:
HubSection hs = new HubSection()
{
ContentTemplate = Application.Current.Resources[HUBSECTION_TEMPLATE] as DataTemplate,
DataContext = model,
Tag = model.UniqueId,
};
Hub.Sections.Insert(firstSectIdx + 1, hs);
public class Model
{
public Guid UniqueId {get;set;}
public List<ItemModel> MyNodes {get;set;}
}
public class ItemModel
{
public string MyText {get;set;}
}
PS:ItemModel在另一个程序集中定义,因此不应编辑(如果可能,命令应该在Model类中)
---编辑---
为了简化问题,我使用以下模型:
public class Model
{
public Guid UniqueId {get;set;}
public List<ItemModel> MyNodes {get;set;}
public ICommand MyCommand {get;set;}
}
public class ItemModel
{
Model _Model;
public ItemModel(Model m) {_Model = m; }
public string MyText {get;set;}
public ICommand MyCommand { get { return _Model.MyCommand; }}
}
我的(临时)解决方案是使用itemtemplate中的按钮:
<ListView.ItemTemplate>
<DataTemplate>
<Button HorizontalAlignment="Stretch" Command="{Binding TapCommand}" Height="64">
<TextBlock Text="{Binding MyText}" />
</Button>
</DataTemplate>
</ListView.ItemTemplate>
答案 0 :(得分:9)
您可以使用行为SDK 。
在Visual Studio中,转到“工具 - &gt;扩展和更新'并安装Behaviors SDK(XAML)。然后使用“添加引用”对话框在项目中引用它。
之后,将以下命名空间添加到您的页面:
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
现在,您可以使用以下语法注册诸如点击堆栈面板之类的事件:
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="64">
<TextBlock Text="{Binding MyText}" />
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding YourCommand}"/>
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</StackPanel>
</DataTemplate>
但是,只有在ItemModel
类中定义了Command时,此代码才有效。如果要绑定到父元素Command,可以尝试这样的(未测试):
{Binding ElementName=LayoutRoot, Path=DataContext.ParentCommand}
但我会优先对你的ItemModel
班级发出指令
修改:没有行为SDK的解决方案:
如果您使用ListView
(或从ListViewBase
继承的内容),则可以使用ItemClick事件。为了使它更具可重用性和Mvvm友好性,你可以像这样实现你的DependencyProperty:
public static class ItemClickCommand
{
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command", typeof(ICommand),
typeof(ItemClickCommand), new PropertyMetadata(null, OnCommandPropertyChanged));
public static void SetCommand(DependencyObject d, ICommand value)
{
d.SetValue(CommandProperty, value);
}
public static ICommand GetCommand(DependencyObject d)
{
return (ICommand)d.GetValue(CommandProperty);
}
private static void OnCommandPropertyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var control = d as ListViewBase;
if (control != null)
{
control.ItemClick += OnItemClick;
}
}
private static void OnItemClick(object sender, ItemClickEventArgs e)
{
var control = sender as ListViewBase;
var command = GetCommand(control);
if (command != null && command.CanExecute(e.ClickedItem))
{
command.Execute(e.ClickedItem);
}
}
}
然后你的ListView将如下所示:
<ListView
IsItemClickEnabled="True"
helpers:ItemClickCommand.Command="{Binding YourCommand}"
ItemsSource="{Binding MyNodes}"
ItemTemplate="{StaticResource YourDataTemplate}" />
在这种情况下,您的子项目作为参数传递给您的命令,因此它也应该解决您在父模型中定义的Command的问题。