I have WPF MVVM application and I am currently trying to use a Checkbox that is bound to a column in a list that it is bound to. I have a EventTriggers set and the command bound to the VM. Everything fires great....Except I do NOT want the events to fire when populated from the list, ONLY when the user checks or unchecks the checkbox. See Code:
<StackPanel Orientation="Vertical" Background="Transparent" DockPanel.Dock="Right" Margin="2,0" VerticalAlignment="Center">
<Label Content="Active" />
<CheckBox x:Name="CbArchiveAoi" VerticalAlignment="Center" HorizontalAlignment="Center" FlowDirection="RightToLeft" IsChecked="{Binding Path=PatientAoi.AoiIsActive}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding ArchiveAoiCommand, Mode=OneWay}"
CommandParameter="{Binding ElementName=CbArchiveAoi}"/>
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<i:InvokeCommandAction Command="{Binding ArchiveAoiCommand, Mode=OneWay}" CommandParameter="{Binding ElementName=CbArchiveAoi}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</StackPanel>
public ICommand ArchiveAoiCommand
{
get { return new RelayCommand<object>(ArchiveAoiExecute, AlwaysTrueCanExecute); }
}
private void ArchiveAoiExecute(object obj)
{
string dddd = obj.ToString();
}
I'd remove the Interaction.Triggers and use the CheckBox.CommandandCommandParameter properties instead.
<CheckBox x:Name="CbArchiveAoi"
VerticalAlignment="Center"
<-- snip -->
Command="{Binding ArchiveAoiCommand, Mode=OneWay}"
CommandParameter="{Binding ElementName=CbArchiveAoi}" />
Related
So basically I have a class Step.
public class Step : INotifyPropertyChanged
{
public int Index { get; set; }
public int Time { get; set; }
}
In my xaml, I want to represent Steps using one DataTemplate and an ItemsControl. My DataTemplate looks like this:
<DataTemplate x:Key="StepTemplate" DataType="data:Step">
<Label Content="{Binding Index}"/>
<Label Content="{Binding Time}"/>
</DataTemplate>
And my ItemsControl looks like this.
<ItemsControl Name="ListSteps" ItemsSource="{Binding Steps}" Grid.IsSharedSizeScope="True" ItemTemplate="{StaticResource StepTemplate}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="{Binding Path=DataContext.StepClick, ElementName=ListSteps}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ItemsControl>
So pretty much what should happen: Whenever I click on a Step, the method StepClick gets called and the Step object that I clicked on is passed as a parameter.
What is actually happening: Whenever I click on a Step, the method StepClick gets called, but not the Step Object gets passed as a parameter but an object of my view gets passed. Which is not at all what I want.
How can I pass an object of Step whenever I click on a Step?
Move the interaction trigger to the root element of the ItemTemplate:
<DataTemplate x:Key="StepTemplate" DataType="data:Step">
<StackPanel Background="Transparent">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="{Binding Path=DataContext.StepClick, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Label Content="{Binding Index}"/>
<Label Content="{Binding Time}"/>
</StackPanel>
</DataTemplate>
I have the following situation:
1. I have Window Load event - which gets the SourceItems for a ComboBox
2. ComboBox have EventTrigger for Selection Changed and the following XAML:
<ComboBox x:Name="uxEnvironmentsComboBox"
ItemsSource="{Binding Environments}" Width="90" Margin="0,10,160,0"
HorizontalAlignment="Right"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Center"
IsSynchronizedWithCurrentItem="True" SelectedIndex="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectEnvironment}"
CommandParameter="{Binding Path=SelectedItem, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ComboBox}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
Everything works, the Window Load properly, the List is populated in the ComboBox, but when the default selection is made my <i:EventTrigger EventName="SelectionChanged"> does not trigger and the rest of the application configuration is not triggered unless I make a manual selection change ?!
SelectEnvironment should be a property that you bind to:
<ComboBox x:Name="uxEnvironmentsComboBox"
ItemsSource="{Binding Environments}" Width="90" Margin="0,10,160,0"
SelectedItem="{Binding SelectEnvironment}"
HorizontalAlignment="Right"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Center"
IsSynchronizedWithCurrentItem="True" SelectedIndex="0">
</ComboBox>
You can invoke any command in the setter of this property if you want to:
private Environment _selectEnvironment;
public Environment SelectEnvironment
{
get { return _selectEnvironment; }
set
{
_selectEnvironment = value;
//invoke command
YourCommand.Execute(_selectedEnvironment);
}
}
And if you want to invoke the command or set the property initially, you could for example do this in the constructor of the view model. You don't need to use an InvokeCommandAction.
I have the following code. No checked/ unchecked event is fired when PlayVideoState value is set to true/false. Does anything missing? please suggest.
<CheckBox Style="{DynamicResource PlayButton}" Margin="6" Name="PlayButton" IsChecked="{Binding _Extensions.PlayVideoState, Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<ei1:GoToStateAction StateName="VideoOn"/>
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<ei1:GoToStateAction StateName="VideoOff"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBlock x:Name="textBlock2" FontFamily="{DynamicResource FontFamily1}" Foreground="{DynamicResource Text01}" Margin="0" VerticalAlignment="Center" FontSize="21.333"><Run Language="en-gb" Text="Video"/></TextBlock>
</CheckBox>
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.
I want to write the event for list box from View Model. I try like this:-
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Gray" Padding="5" BorderThickness="1">
<StackPanel Orientation="Horizontal">
<Border BorderBrush="Wheat" BorderThickness="1">
<Image Name="ListPersonImage" Source="{Binding PersonImage}" Height="100" Width="100" Stretch="Uniform" Margin="10,0,0,0"/>
</Border>
<TextBlock Text="{Binding FirstName}" Name="firstName" Width="200" Foreground="White" Margin="10,10,0,0" FontWeight="SemiBold" FontSize="22" />
<Button DataContext="{Binding DataContext, ElementName=listBox1}" Command="{Binding addPerson}" Height="80" Width="80" >
<Button.Background>
<ImageBrush ImageSource="{Binding imagePath, Converter={StaticResource pathToImageConverter}}" Stretch="Fill" />
</Button.Background>
</Button>
</StackPanel>
</Border>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<i:InvokeCommandAction Command="{Binding ItemSelectedCommand,Mode=OneWay}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My ViewModel:-
public RelayCommand<MVVMListBoxModel> ItemSelectedCommand { get; private set; }
public MVVMListBoxViewModel()
{
ItemSelectedCommand = new RelayCommand<MVVMListBoxModel>(ItemSelected);
}
private void ItemSelected(MVVMListBoxModel myItem)
{
MessageBox.Show("Name==>" + myItem.FirstName);
//throw new NotImplementedException();
}
But nothing happening. Please let me know where I did mistake.
Thanks in advance.
Check output window to see if you got binding error. It seems that you got one, because you have ItemSelectedCommand defined in MVVMListBoxViewModel but ListBoxItem's DataContext is corresponding MVVMListBoxModel, so binding engine couldn't find the command.
Try to move definition of ItemSelectedCommand to MVVMListBoxModel and see if message box get displayed this way.
Do you want the trigger to be upon the SelectionChanged of the Listbox Item? Then the trigger should be outside the <ListBox.ItemTemplate> ... </ListBox.ItemTemplate>.
And the trigger should bind the CommandParamter to the SelectedItem
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<i:InvokeCommandAction Command="{Binding ItemSelectedCommand,Mode=OneWay}" CommandParameter="{Binding SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>