如何将命令绑定到StackPanel或Grid tap事件?

Jea*_*ean 4 c# xaml windows-phone-8.1

我已经看到了一些关于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>
Run Code Online (Sandbox Code Playgroud)

这是从代码中使用它的方式:

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;}
}
Run Code Online (Sandbox Code Playgroud)

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; }}
}
Run Code Online (Sandbox Code Playgroud)

我的(临时)解决方案是使用itemtemplate中的按钮:

    <ListView.ItemTemplate>
        <DataTemplate>
            <Button HorizontalAlignment="Stretch"  Command="{Binding TapCommand}" Height="64">
                <TextBlock Text="{Binding MyText}" />
            </Button>
        </DataTemplate>
    </ListView.ItemTemplate>
Run Code Online (Sandbox Code Playgroud)

Ond*_*unc 10

您可以使用Behaviors SDK.
在Visual Studio中,转到"工具 - >扩展和更新"并安装Behaviors SDK(XAML).然后使用"添加引用"对话框在项目中引用它.
之后,将以下命名空间添加到您的页面:

xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用以下语法注册诸如点击堆栈面板之类的事件:

<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>
Run Code Online (Sandbox Code Playgroud)

但是,只有在ItemModel类中定义了Command时,此代码才有效.如果要绑定到父元素Command,可以尝试这样的(未测试):

{Binding ElementName=LayoutRoot, Path=DataContext.ParentCommand}
Run Code Online (Sandbox Code Playgroud)

但是我会优先在你的ItemModel类上使用命令


编辑:没有Behaviors 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你的ListView将如下所示:

<ListView 
    IsItemClickEnabled="True" 
    helpers:ItemClickCommand.Command="{Binding YourCommand}"
    ItemsSource="{Binding MyNodes}"
    ItemTemplate="{StaticResource YourDataTemplate}" />
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您的子项将作为参数传递给您的命令,因此它还应该解决您在父模型中定义的Command的问题.