I have this Passwordbox with this trigger :
<PasswordBox>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PasswordChanged">
<i:InvokeCommandAction Command="{Binding PasswordChanged}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</PasswordBox>
How can I, in my RelayCommand, get the content of my PasswordBox?
This is my relay command :
PasswordChanged = new RelayCommand<object>(param => this.GoPasswordChanged());
private void GoPasswordChanged()
{
}
I found the solution, I had just to change :
<i:InvokeCommandAction Command="{Binding PasswordChanged}" />
To :
<i:InvokeCommandAction Command="{Binding PasswordChanged}" CommandParameter="{Binding ElementName=PasswordBoxInput}" />
And :
PasswordChanged = new RelayCommand<object>(param => this.GoPasswordChanged(param));
private void GoPasswordChanged(param)
{
}
To :
private void GoPasswordChanged(object param)
{
var passwordBox = param as PasswordBox;
var password = passwordBox.Password;
}
Related
So this is what i have try:
<TextBox Name="TextBoxLatter">
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyDown">
<i:InvokeCommandAction Command="{Binding Path=TextBoxKeyDownCommand}"
CommandParameter="{Binding ElementName=TextBoxLatter, Path=Text}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
And inside my Execute method my parameter is null:
public void Execute(object parameter)
{
}
Your current approach should work if you handle the KeyUp event instead of KeyDown.
But you should bind the Text property of TextBoxLatter to a string source property of the view model. You could then access it directly in the Execute method of the command:
public void Execute(object _)
{
string text = this.YourProperty;
//...
}
XAML:
<TextBox Name="TextBoxLatter" Text="{Binding YourProperty, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyDown">
<i:InvokeCommandAction Command="{Binding Path=TextBoxKeyDownCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
<TreeView x:Name="TestTree"
ItemsSource="{Binding Children}"
ItemTemplateSelector="{StaticResource TemplateSelector}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="TreeViewItem.Seleted">
<i:InvokeCommandAction
Command="{Binding SelectedCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TreeView>
As above codes mentioned, I wanna get the selected treeviewitem data from the view, while the binding event TreeViewItem.Seleted which is an attached event(member event is okay) cannot be received in the viewmodel. How to binding an attached event to viewmodel?
then, you won't get TreeViewItem event in the TreeView ? you need a custom item template. I do it like this on a datagrid with MVVMLight (but no item)
</DataGrid.Columns>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick" >
<command:EventToCommand Command="{Binding Path=OpenEquipementCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
<i:EventTrigger EventName="SelectionChanged">
<command:EventToCommand Command="{Binding Path=SelectionChangedCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
so i think you must do
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged" >
<command:EventToCommand Command="{Binding Path=SelectionChangedCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
Why don't just use plain old eventhandler?
<TreeView x:Name="TreeView1" SelectedItemChanged="TreeView_SelectedItemChanged" />
public partial class MainWindow : Window
{
MainWindowViewModel ViewModel => (MainWindowViewModel) DataContext;
private void TreeView1_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
var element = (FrameworkElement)sender;
var item = element.DataContext;
ViewModel.SelectionChangedCommand.Invoke(item);
//alternativelly:
ViewModel.SelectedItem = TreeView1.SelectedItem;
}
}
Just because WPF support binding, it does not mean you have to use it everywhere even if it's very complicated. The code I've written is not violation of MVVM.
If you have a good reason to avoid code behind, you may implement this eventhandler in a custom behavior implemented as attached property, so it would look like this:
<TreeView local:TreeViewBehavior.SelectionChangedCommand="{Binding SelectionChangedCommand}" />
Do you know is it possible to get element on MouseOver from ListView in WPF using XAML?
I would like to bind mouse over element to command parameter.
What should I type in Path ?
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<i:InvokeCommandAction Command="{Binding SetOnMousePlayerCommand}"
CommandParameter="{Binding ElementName=leftPlayersListViewGame, Path=XXX}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Probably I have to do it in another way ? Could you tell my how ?
if you are looking to access the Event Args here how you should proceed:
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<command:EventToCommand Command="{Binding Mode=OneWay,Path=MouseEnterCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
private RelayCommand<MouseEventArgs> _mouseEnterCommand;
public RelayCommand<MouseEventArgs> MouseEnterCommand
{
get
{
return _mouseEnterCommand
?? (_mouseEnterCommand= new RelayCommand<MouseEventArgs>(
(s) =>
{
//your logic
}));
}
}
but if you are looking for the sender of the Event, so here is your answer Pal :
Passing event args and sender to the RelayCommand
I have some academic question here. Look at markup:
<Grid Margin="10,10,10,10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ComboBox SelectedIndex="{Binding SelectedIndex}"
Margin="5"
Width="100">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding TestCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ComboBox},
Path=SelectedIndex}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ComboBoxItem>Item1</ComboBoxItem>
<ComboBoxItem>Item2</ComboBoxItem>
<ComboBoxItem>Item3</ComboBoxItem>
</ComboBox>
<Button Grid.Row="1"
Content="Set SelectedIndex to 0"
Width="100"
Command="{Binding ButtonCommand}"
Margin="5">
</Button>
</Grid>
This is DataContext class.
class Class1Context : ViewModelBase
{
private int _selectedIndex;
public Int32 SelectedIndex
{
get { return _selectedIndex; }
set
{
_selectedIndex = value;
RaisePropertyChanged("SelectedIndex");
}
}
private RelayCommand<Object> _testCommand;
public RelayCommand<Object> TestCommand
{
get
{
return _testCommand ?? (_testCommand =
new RelayCommand<Object>(TestMethod));
}
}
private void TestMethod(Object obj)
{
var index = (Int32) obj;
var selIndex = SelectedIndex;
}
private RelayCommand _buttonCommand;
public RelayCommand ButtonCommand
{
get
{
return _buttonCommand ?? (_buttonCommand =
new RelayCommand(ButtonCommandMethod));
}
}
private void ButtonCommandMethod()
{
SelectedIndex = 0;
}
}
So, where is the problem? Here it is. When I select Item2 or Item3, then SelectedIndex property equals 1 or 2. For example, I clicked Item2 and SelectedIndex equals 1 now. Hence, when I click the Button and set SelectedIndex to 0 it generates the event SelectionChanged in Combobox. It is logically. Then, event fires the bounded command TestCommand.
And in TestMethod index (CommandParameter) equals to 1 (one!) and it is a problem, in spite of SelectedIndex of DataContext equals to 0 (zero).
So, is it a Wpf bug or something else?
I did it like this:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
<ComboBox>
<ComboBox.Items>
<ComboBoxItem Content="item1" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Selected">
<i:InvokeCommandAction Command="{Binding item1Cmd}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBoxItem>
<ComboBoxItem Content="item2" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Selected">
<i:InvokeCommandAction Command="{Binding item2Cmd}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBoxItem>
<ComboBoxItem Content="item3" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Selected">
<i:InvokeCommandAction Command="{Binding item3Cmd}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBoxItem>
</ComboBox.Items>
</ComboBox>
This way worked fine for me. I'm aware of a little code overhead using the same code for each ComboBoxItems.
If your ComboBox is needs a dynamic load then you should be able to add the Interaction.Triggers in code behind
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding TestCommand}" ></i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
i'm trying to Raise a PropertyChanged event on a Property in my ViewModel
using interaction triggers .
CS :
public string MyContentProperty
{
get { return "I Was Raised From an outside Source !";}
}
XAML :
<Button Content="{Binding MyContentProperty}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Button.Click">
< .... what needs to be done ?>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
of course if there was any doubt for this question you have references to
xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
at your disposal , thanks in advance .
You can use a normal command or Expression Blend's CallMethodAction, InvokeCommandAction or ChangePropertyAction.
Here are four ways to do what you want:
<Button Content="Button" Height="23" Width="100" Command="{Binding RaiseItCmd}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding RaiseItCmd}"/>
<ei:CallMethodAction MethodName="RaiseIt" TargetObject="{Binding}"/>
<ei:ChangePropertyAction Value=""
PropertyName="MyContentProperty" TargetObject="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
Here I'm using MVVM Light's ViewModelBase:
using System.Windows.Input;
using GalaSoft.MvvmLight;
using Microsoft.Expression.Interactivity.Core;
public class ViewModel : ViewModelBase
{
public ViewModel()
{
RaiseItCmd = new ActionCommand(this.RaiseIt);
}
public string MyContentProperty
{
get
{
return "property";
}
set
{
this.RaiseIt();
}
}
public void RaiseIt()
{
RaisePropertyChanged("MyContentProperty");
}
public ICommand RaiseItCmd { get; private set; }
}