2015-05-10 6 views
2

Я видел некоторые ответы, касающиеся WP8 или других, однако, кажется, что нет триггеров в WP8.1 (Или я что-то не хватает?)Как связать команду с событием StackPanel или Grid?

У меня есть DataTemplate связаны с кодом (он является центром DataTemplate , и у меня есть смесь статических и динамических узлов, поэтому этот набор данных необходимо установить из кода).

Этот шаблон данных определен в отдельном файле xaml, он включает в себя список (или список) с другим набором данных, определенным для элементов.

Мне нужно связать команду на кране элемента или списке выбора (или что-то подобное). Однако событие нажатия, определенное в шаблоне, не вызывается, поэтому я думал о привязке команды к элементу пользовательского интерфейса, но они, похоже, не поддерживают 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 определяется в другой сборке и поэтому не должны быть отредактированы (команда должна быть в классе модели, если это возможно)

--- EDIT ---

для того, чтобы упростить проблему, я использую следующие модели:

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

А что, вместо прямого использования StackPanel, оберните его стилизованной кнопкой? Таким образом, у вас есть привязка Button Command, которую вы можете использовать для перехвата кликов. Другое дело, вы просите выбрать элемент или выбор элемента. Остерегайтесь того, что они ведут себя по-другому, если вы выберете один и тот же элемент дважды, щелчок будет срабатывать, но селектин не изменится. –

+0

Что касается поведения, это не имеет особого значения, поскольку я создаю что-то вроде файлового проводника, поэтому, если элемент прослушивается, что-то должно произойти и не может произойти дважды. Если я не найду другого варианта, я закончу использование кнопки, но мне не очень нравится использовать кнопку, когда она не должна быть такой. – Jean

+0

Я отредактировал ваш заголовок. Пожалуйста, смотрите: «Если вопросы включают« теги »в их названиях?] (Http://meta.stackexchange.com/questions/19190/), где консенсус« нет, они не должны ». –

ответ

9

Вы можете использовать Behaviors SDK.
В Visual Studio перейдите в раздел «Инструменты -> Расширение и обновления» и установите «Поведение» 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. Если вы хотите связать с командой родительского элемента, вы можете попробовать что-то вроде этого (не проверено):

{Binding ElementName=LayoutRoot, Path=DataContext.ParentCommand} 

Но я бы preferer имея команду на вашем ItemModel класса


Edit: Solution без поведений 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}" /> 

В этом случае ваш ребенок элемент передается к вашей команде, как параметр, поэтому он также должен решить вашу проблему с помощью вашей команды, определенной в родительской модели.

+0

Это то, что я искал, однако я не могу его найти. Я использую Visual Studio 2015 RC, возможно, поэтому он недоступен в качестве расширения? – Jean

+0

Я использую VS 2013, поэтому я понятия не имею, что вызывает проблему. Я отправляю другое решение без SDK Behaviors. Надеюсь, поможет. –

+0

Я видел это, у меня еще не было времени попробовать, однако это похоже на приятное решение, и это было более или менее такое решение, которое я искал, спасибо! :) – Jean

Смежные вопросы