I have a hub control on my main page and in the HubSection header i cant get the element to fire when i click on the button, however when i move the XAML into the DataTemplate the event if fired. Can you please explain to me why this is, do i need to enable something in the HubSection.Header so that the event can fire?
here is the code that doesn't fire:
<HubSection >
<HubSection.Header>
<StackPanel >
<TextBlock
Text="{Binding
WhatToWatch.Name,
Mode=OneWay}" />
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction
Command="{Binding ViewMoreCommand}"
CommandParameter="{Binding WhatToWatch.Name}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</StackPanel>
</HubSection.Header>
<DataTemplate>
<controls:RowGridView
ItemsSource="{Binding
WhatToWatch.Data,
Mode=TwoWay}" />
</DataTemplate>
</HubSection>
And here is the code that does fire the Event:
<DataTemplate>
<StackPanel >
<StackPanel >
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding ViewMoreCommand}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
<TextBlock
Text="{Binding
WhatToWatch.Name,
Mode=OneWay}" />
</StackPanel>
<controls:RowGridView
ItemsSource="{Binding
WhatToWatch.Data,
Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</HubSection>
Its the same code, but in the second one the core:InvokeCommandAction action is in the DataTemplate, is this what allows the XAML to call the event? why is this so?
You have to put a reference to your page that owns the ViewModel.
Set a name for your page for example: "pageRoot"
then change your Behavior to
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding DataContext.ViewMoreCommand, ElementName=pageRoot}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
Related
In my app using the Windows App SDK, I'm trying to get a button-tapped event to trigger a command in my viewmodel. I have gotten this to work when the data template is between the and on the page, but it won't work when the data template is in Page.Resources. I have to place some data templates in Page.Resources because I need to have multiple data templates in the TreeView and use a DataTemplateSelector to select the correct one based on the type of the item. I've gotten the template selection working, but I just can't get the button binding to work. It looks like the ElementName binding can't find the page name. Can anyone show me what I'm doing wrong?
<Page.Resources>
<DataTemplate x:Key="treeViewSFTemplate" x:DataType="models:SF">
<TreeViewItem ItemsSource="{Binding OwnedSFEs}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding SFName}"/>
<Button Content="+">
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding ElementName=sfSettingsPage, Path=ViewModel.AddNewSubfactorCommand}"/>
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
</Button>
<Button Content="-"/>
</StackPanel>
</TreeViewItem>
</DataTemplate>
<DataTemplate x:Key="treeViewSFETemplate" x:DataType="models:SFE">
<TreeViewItem>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding SFEName}"/>
<Button Content="+">
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding ElementName=thisPage, Path=ViewModel.DeleteSFECommand}"/>
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
</Button>
<Button Content="-"/>
</StackPanel>
</TreeViewItem>
</DataTemplate>
</Page.Resources>
And then in the in the page code below:
<TreeView x:Name="MyTreeView"
ItemsSource="{x:Bind ViewModel.SFList}"
ItemTemplateSelector="{StaticResource treeViewDataTemplateSelector}" />
The reason for this behavior is that you wrapped a TreeViewItem in
the DataTemplate. It will cause that TreeViewItem contains sub-TreeViewItem in the Visual Tree and you could not access correct DataContext with element name in your button. Please remove TreeViewItem from your code.
Like:
<DataTemplate x:Key="treeViewSFETemplate" x:DataType="models:SFE">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding SFEName}"/>
<Button Content="+">
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding ElementName=thisPage, Path=ViewModel.DeleteSFECommand}"/>
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
</Button>
<Button Content="-"/>
</StackPanel>
</DataTemplate>
Assuming the view model MyViewModel for the page is bound to the DataContext property of the page and MyItemViewModel is the datatype of the item in a collection. The CommandParameter binding binds the view model of the item:
<Page
...
x:Name="MyPage"
...
<Page.Resources>
...
<DataTemplate x:Key="MyDataTemplate" x:DataType="vm:MyItemViewModel>
...
<Button
...
Command="{Binding ElementName=MyPage, Path=DataContext.MyCommand}"
CommandParameter="{Binding}"
...
Changes to the value of the property DataContext can be verified by adding an eventhandler after InitializeComponent() in the page constructor:
public MyPage()
{
InitializeComponent();
...
DataContextChanged += MyPage_DataContextChanged;
...
}
void MyPage_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
{
if (DataContext is MyViewModel vm)
{
}
}
I've got following problem. Following situation in my xaml code:
<ListView ItemsSource="{Binding ListViewItems}">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<Label Content="Test">
<Label.ContextMenu>
<ContextMenu ItemsSource="{Binding MenuItems}">
</ContextMenu>
</Label.ContextMenu>
</Label>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseUp">
<i:InvokeCommandAction Command="{Binding LabelMouseUpCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListView>
After clicking a label no context menu is shown and the trigger does not work as well, LabelMouseUpCommand method is not entered. I fear the listview handles the click itself and does not pass it to the embedded controls.
Is there any way to pass it to the controls. In future i want to add several controls to the itemtemplate and everyone has it own different context menu.
I found the answer for my problem with this stackoverflow article
There the author explains that the contextmenu does not lie in the same visual tree as the listview. Therefore my initial binding can't work because the source can't be found within the visual tree.
Furthermore Sinatr was totally right, the trigger was initially defined for listview, not for the label.
Here is my working code:
<ListView ItemsSource="{Binding ListViewItems}" x:Name="listViewMain">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<Label Content="Test">
<Label.ContextMenu>
<ContextMenu ItemsSource="{Binding DataContext.MenuItems, Source={x:Reference listViewMain}}">
</ContextMenu>
</Label.ContextMenu>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseUp">
<i:InvokeCommandAction Command="{Binding DataContext.LabelMouseUpCommand, Source={x:Reference listViewMain}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Label>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
After I upgraded to Wp8.1 silverlight my listpicker fails during runtime, when InitializeComponent(); is executed.
The WPtoolKit where the listpicker comes from, has been updated, but still in my solution is: \packages\WPtoolkit.4.2013.08.16\lib\wp8\Microsoft.Phone.Controls.Toolkit.dll.
The list picker is displayed in the xaml design view and the code is:
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
.
.
.
<StackPanel Grid.Row="0" Grid.RowSpan="3" Orientation="Horizontal" >
<toolkit:ListPicker x:Name="LP_Map" Width="284" Template="{StaticResource ListPicker_ChooseCountry_CreateGame_test}" BorderBrush="#FF884900">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand Command="{Binding ChangeMapCommand}" CommandParameter="{Binding ElementName=LP_Map}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<toolkit:ListPickerItem Background="#FFAB7D33" Content="Europe1328WithWater" Foreground="Black" Style="{StaticResource ListPickerItem_CreateGame_ChooseCountry_test}" />
</toolkit:ListPicker>
<toolkit:ListPicker x:Name="Player_LP" Width="150" SelectionChanged="SelChangedCommand" BorderBrush="#FF884900" Foreground="Black">
<toolkit:ListPickerItem Background="#FFAB7D33" Content="2 Players" Foreground="Black" FontFamily="Andalus" />
<toolkit:ListPickerItem Background="#FFAB7D33" Content="3 Players" FontFamily="Andalus" />
<toolkit:ListPickerItem Background="#FFAB7D33" Content="4 Players" FontFamily="Andalus" />
</toolkit:ListPicker>
</StackPanel>
I do not understand why I get an XAML parse error, is there something I need to update explicitly or change after the re-targeting of the solution?
Note
EventToCommand using MVVMLight is not the issue, this has been updated to use the parameter package.
ComboBox is not available in Windows Phone 8.1 Silverlight.
I'm working on WP8.1 Silverlight solution currently, using the latest version of WP phonetoolkit. Have no problem using ListPicker. Here is example:
xmlns:Local="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
<toolkit:ListPicker
x:Name="MyListBox"
BorderBrush="{StaticResource AppBackground}"
Foreground="{StaticResource AppTextColor}"
ItemsSource="{Binding Categories}">
<Local:Interaction.Triggers>
<Local:EventTrigger EventName="SelectionChanged">
<Local:InvokeCommandAction Command="{Binding DataContext.OpenCategoryCMD, ElementName=LayoutRoot}"
CommandParameter="{Binding ElementName=MyListBox, Path=SelectedIndex}"/>
</Local:EventTrigger>
</Local:Interaction.Triggers>
</toolkit:ListPicker>
And in ViewModel:
private void OpenCategory(int categoryIndex) { ... }
I've tried to solve the following problem for several hours now:
I'm developing a game, where I have to switch between several views. When I'm in the game view, at the end there is a button called "Return match" which navigates back to the "PlayerSelectView" where the players are set up:
<Button Tag="{Binding Source={StaticResource Options}, Path=Effect}" Width="300" MinHeight="70">
<localControls:DropShadowTextBlock Text="{Binding LocalizedText.GV_ReturnMatch}"/>
<i:Interaction.Triggers>
<ic:DataTrigger Binding="{Binding Result, ElementName=MessageBoxBehavior}" Value="OK">
<i:InvokeCommandAction Command="{Binding NewGameCommand}" />
<ic:NavigateToPageAction TargetPage="/Views/PlayerSelectView.xaml" />
</ic:DataTrigger>
</i:Interaction.Triggers>
<i:Interaction.Behaviors>
<behaviors:MessageBoxBehavior x:Name="MessageBoxBehavior" Text="{Binding LocalizedText.MAIN_YouWillLoseYourPreviousGame}" IsEnabled="{Binding IsGameInitialized}" />
</i:Interaction.Behaviors>
</Button>
The NewGameCommand doesn't reset the players list in the PlayerSelectViewModel.
At this time the constructor of PlayerSelectView and the constructor in the PlayerSelectViewModel is not called, so it preserves the state, as it should be, but, going back to the menu during the game with this code:
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
GameViewModel.Instance.GameIsPaused = true;
NavigationService.Navigate(new Uri("/Views/MainPageView.xaml", UriKind.Relative));
}
and after that going back to the GameView with the Continue button:
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="{Binding IsGameInitialized, Converter={StaticResource BoolToVisibilityConverter}}" Tag="{Binding Source={StaticResource Options}, Path=Effect}" Width="300" MinHeight="70" FontWeight="Normal">
<localControls:DropShadowTextBlock Text="{Binding LocalizedText.MAIN_Continue}"/>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<ic:NavigateToPageAction TargetPage="/Views/GameView.xaml" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
When I now hit "Return Match", the PlayerSelectView always gets reinitialized!
Why does it now reinitialize the PlayerSelectView? The other thing is, that when the new players are set up again and the game is started, it just returns to the Game Over screen (which is a popup layer on the GameView).
Does anyone have an idea what to do?
UPDATE:
When the game starts, the MainView is shown. From there the user is taken to the PlayerSelectView with this button:
<Button Tag="{Binding Source={StaticResource Options}, Path=Effect}" Width="300" MinHeight="70">
<localControls:DropShadowTextBlock Text="{Binding LocalizedText.MAIN_NewGame}"/>
<i:Interaction.Triggers>
<ic:DataTrigger Binding="{Binding Result, ElementName=MessageBoxBehavior}" Value="OK">
<i:InvokeCommandAction Command="{Binding NewGameCommand}" />
<ic:NavigateToPageAction TargetPage="/Views/PlayerSelectView.xaml" />
</ic:DataTrigger>
</i:Interaction.Triggers>
<i:Interaction.Behaviors>
<behaviors:MessageBoxBehavior x:Name="MessageBoxBehavior" Text="{Binding LocalizedText.MAIN_YouWillLoseYourPreviousGame}" IsEnabled="{Binding IsGameInitialized}" />
</i:Interaction.Behaviors>
</Button>
Here players are created and edited. The game starts with this button:
<Button Command="{Binding StartGameCommand}" CommandParameter="{Binding NavigationService, ElementName=PlayerSelectViewControl}" Tag="{Binding Source={StaticResource Options}, Path=Effect}" Padding="0">
<localControls:DropShadowTextBlock Text="{Binding LocalizedText.PLSEL_StartGame}"/>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<ic:NavigateToPageAction TargetPage="/Views/GameView.xaml"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
...which runs this code as well:
private void StartGame()
{
BusinessLogic.GameLogic.Initialize(new List<Player>(Players));
}
From there, the user can go back to the MainView (menu), exit the game (the state is preserved) or change options.
This is a pretty easy question I think , but I can't find the answer. I have an itemtemplate defined into a datatemplate. When an item is selected, I wanna trigger a command to select the name of my element and apply it somewhere else. For the moment the MouseDown event doesn't accept my command.
<ListView Margin="4" Grid.Row="1" Grid.ColumnSpan="2" ItemsSource="{Binding Path=ExistingStateInfos, ElementName=Window}"
SelectedItem="{Binding Path=SelectedStateInfo, ElementName=Window}" x:Name="statinfoListview">
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type States:StateInfo}">
<TextBlock Text="{Binding Path=Name}" MouseDown="{x:Static MyWindow.ApplyStateInfoNameToStateCommand}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
You can't set a command directly to an event handler.
Use EventToCommand from the MVVM LightToolkit
<DataTemplate DataType="{x:Type States:StateInfo}">
<TextBlock Text="{Binding Path=Name}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<Command:EventToCommand Command="{Binding YourCommand, Mode=OneWay}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</DataTemplate>
In fact ot was bulshit from me, I just add to do
<TextBlock Text="{Binding Path=Name}" MouseDown="{x:Static ApplyStateInfoNameToState_Click}" />
Sorry it's friday. Have a nice weekend :)