So I use the Autosuggestionbox of the ModernWPF Toolkit and was trying to get to handle the "QuerySubmitted" event from it via the MVVM way. Here's what I have
<ui:AutoSuggestBox x:Name="TextBox"
Text="{Binding TextBoxID, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ItemsSource="{Binding Path= TextBoxCollection}"
>
<i:Interaction.Triggers>
<i:EventTrigger EventName="QuerySubmitted" >
<i:InvokeCommandAction Command ="{Binding QuerySubmit}" CommandParameter="{Binding ElementName=TextBox}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ui:AutoSuggestBox>
Heres my ViewModel
public ICommand textBox
public ICommand QuerySubmit
{
get
{
if(textBox== null)
{
///Do some stuff when event fires
}
return textBox;
}
}
and for the namespace of i its
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
But it doesn't seem to work so far. Any guesses on why and how to fix it?
To add, I tried switching it to a different event (MouseDoubleClick) and it works, so I think it's about the event of the querysubmit itself.
Related
How do i trigger the SourceUpdate of my wpf listview?
This is my xaml
<ListView DataContext="{StaticResource vmInstance}" SelectedItem="{Binding selectedItem}" BorderBrush="Beige" BorderThickness="1" ItemsSource="{Binding lstExternal}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged" >
<cmd:EventToCommand Command="{Binding Path=ItemChanged}"
PassEventArgsToCommand="True" />
</i:EventTrigger>
<i:EventTrigger EventName="SourceUpdated">
<cmd:EventToCommand Command="{Binding Path=SourceUpdated}"
PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListView.View >
</ListView.View>
</ListView>
ViewModel:
public static RelayCommand SourceUpdated { get; set; }
//on initialize
SourceUpdated = new RelayCommand(SourceUpdateEvent);
public void SourceUpdateEvent()
{
Console.WriteLine("Updated");
}
Why does SourceUpdateEvent doesn't run?
Am I using the wrong event?
Thank you
want to execute a method when the itemsource of the listview is changed or updated
Then bind the ItemsSource property of the ListView to a source property of your view model
<ListView ItemsSource="{Binding YourCollection}" ...>
...and invoke your command in the setter of this source property:
private ObservableCollection<YourType> _sourceCollection;
public ObservableCollection<YourType> SourceCollection
{
get { return _sourceCollection; }
set
{
_sourceCollection = value;
RaisePropertyChanged();
SourceUpdated.Execute(null);
}
}
This is the (only) correct way to solve this using the MVVM pattern.
I am trying to bind a click on button event in WPF to a command defined in a View Model, here is how I am doing that for now :
In the xaml code :
<Grid>
<Button Content="Module A" Background="Green" FontWeight="Bold">
<i:Interaction.Triggers>
<i:EventTrigger EventName="click">
<i:InvokeCommandAction Command="{Binding ChargeModuleDCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
and in the ViewModel class :
class ModuleAViewModel
{
public DelegateCommand<object> ChargeModuleDCommand { get; set; }
public ModuleAViewModel()
{
ChargeModuleDCommand = new DelegateCommand<object>(LaunchDModule);
}
private void LaunchDModule(object parm)
{
Console.WriteLine("I am in the function");
}
}
but it does not work. I've tried to do it as specified in this question : How to trigger ViewModel command for a specific button events
but it does not work either.
Is there any way that I can make it work ?
<Button
Command="{Binding ChargeModuleDCommand}"
Content="Module A"
Background="Green"
FontWeight="Bold"
/>
If ModuleAViewModel is the Button's DataContext, that should work.
What I have:
I have a combobox. Here is its LostFocus using Command in MVVM style:
<ComboBox .............>
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<i:InvokeCommandAction Command="{Binding DataContext.OrderIdLostFocusCommand, UpdateSourceTrigger=PropertyChanged,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
And in the ViewModel:
//Constructor
public DispatchViewModel(IEventAggregator _eventAggregator)
{
eventAggregator = _eventAggregator;
//Some Code
OrderIdLostFocusCommand = new RelayCommand(Execute_OrderId_LostFocus);
}
public RelayCommand OrderIdLostFocusCommand { get; set; }
private void Execute_OrderId_LostFocus(object obj)
{
//Some Calculations
eventAggregator.GetEvent<MoveFocusToDatePickerEvent>().Publish(true);
}
In the Code-Behind:
//Constructor
public DispatchView(DispatchViewModel _viewModel, IEventAggregator _eventAggregator)
{
InitializeComponent();
this.DataContext = _viewModel;
_eventAggregator.GetEvent<MoveFocusToDatePickerEvent>().Subscribe(MoveFocusToDateOfDispatch);
}
private void MoveFocusToDateOfDispatch(bool obj)
{
this.Dispatcher.BeginInvoke((Action)delegate { dpInvoice.Focus(); }, DispatcherPriority.Render);
}
Problem:
When Combobox is focused and if I try to open it's DropDown then its lostfocus event fires and so focus moves to DataPicker.
What I want:
Instead I want to fire LostFocus event only when IsKeyboardFocusWithin property of ComboBox is false.
Just use an interactions DataTrigger on IsKeyboardFocusWithin being false. It's in the http://schemas.microsoft.com/expression/2010/interactions namespace.
<i:Interaction.Triggers>
<ii:DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ComboBox},
Path=IsKeyboardFocusWithin}"
Value="false">
<i:InvokeCommandAction .../>
</ii:DataTrigger>
</i:Interaction.Triggers>
I have a Textbox and for that textbox I have attached a keydown event. Everything is working fine but I just noticed that when i'm pressing the 'Backspace' and 'Delete' Key, the binding command is not being called.
My View xaml file :-
<TextBox x:Name="textBox" Width="500" Text="{Binding TextBoxText, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyDown">
<cmd:EventToCommand Command="{BindingPath=TextBoxKeyDownEvent}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
My ViewModel cs file :-
//TextBox Key Down Event Handler
private DelegateCommand _textBoxKeyDownEvent;
public ICommand TextBoxKeyDownEvent
{
get
{
if (_textBoxKeyDownEvent == null)
{
_textBoxKeyDownEvent = new DelegateCommand(TextBoxKeyDownEventHandler);
}
return _textBoxKeyDownEvent;
}
set { }
}
Can somebody give me some suggestion
EDIT:
You have to use PreviewKeyDown the it works. KeyDown is not fired on Space and Delete. If you ignore MVVM and put the handler of KeyDown in codebehind it will also fail.
How about binding the Text-Property to a string in you viewmodel?
I build a fast, simple example of my idea.
Result
Text from the TextBox on the left side is simply populated to the Textblock on the right side.
View
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding TextBoxValue, UpdateSourceTrigger=PropertyChanged}" Width="250"/>
<StackPanel Orientation="Horizontal">
<TextBlock>"</TextBlock>
<TextBlock Text="{Binding TextBoxValue, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock>"</TextBlock>
</StackPanel>
</StackPanel>
</Window>
ViewModel
public class MainWindowViewModel : INotifyPropertyChanged
{
private string textBoxValue;
public string TextBoxValue
{
get { return textBoxValue; }
set
{
textBoxValue = value;
OnTextBoxValueChanged();
RaisePropertyChanged();
}
}
void OnTextBoxValueChanged()
{
// you logic here, if needed.
}
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
you most use PreviewKeyDown event.
Like this:
<EventSetter Event="PreviewKeyDown" Handler="TextBox_PreviewKeyDown"/>
Edit: You are correct - the default behavior is not executed. You should use ec8ors solution, which is much better anyway:
<TextBox x:Name="textBox" Width="500" Text="{Binding TextBoxText, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewKeyDown">
<i:InvokeCommandAction Command="{Binding TextBoxKeyDownEvent, Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
Original:
You can use InputBindings to call your command when "special" keys have been pressed:
<TextBox x:Name="textBox" Width="500" Text="{Binding TextBoxText, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyDown">
<cmd:EventToCommand Command="{BindingPath=TextBoxKeyDownEvent}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBox.InputBindings>
<KeyBinding Command="{Binding TextBoxKeyDownEvent}" Key="Delete" />
<KeyBinding Command="{Binding TextBoxKeyDownEvent}" Key="Back" />
</TextBox.InputBindings>
</TextBox>
I want to set command parameter to currently selected item on a ListBox.
XAML:
<!--<ListBox ItemsSource="{Binding Places}" SelectedItem="{Binding SelectedPlace, Mode=TwoWay}">-->
<ListBox ItemsSource="{Binding Places}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<i:InvokeCommandAction Command="{Binding ListBoxClick}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
(...)
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
C# (part of ViewModel code exposing the ListBoxClick command)
public RelayCommand ListBoxClick { get; set; }
ListBoxClick = new RelayCommand((o) => {
//model is always null
var model = o as BasicModel;
SelectedPlace = model;
});
I added appropriate references, and namespace:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
The problem is that in action called by RelayCommand object the o parameter is always null.
UPDATE
C# code for SelectedPlace property
public BasicModel SelectedPlace {
get {
return _selectedPlace;
}
set {
_selectedPlace = value;
RaisePropertyChanged("SelectedPlace");
}
}
When I use this:
<ListBox ItemsSource="{Binding Places}" SelectedItem="{Binding SelectedPlace, Mode=TwoWay}">
everything works fine if I click ListBoxItem for the first time, but when I click on a selected ListBoxItem nothing happens, because selection doesn't change. I need to be able to detect item click in both situations.
I figured out an ugly way to achieve my goal.
XAML
<ListBox ItemsSource="{Binding Places}" SelectedItem="{Binding SelectedPlace, Mode=TwoWay}">
C# (ViewModel)
private bool _placeSelected;
public BasicModel SelectedPlace {
get {
return _selectedPlace;
}
set {
_placeSelected = true;
_selectedPlace = value;
RaisePropertyChanged("SelectedPlace");
}
}
ListBoxClick = new RelayCommand((o) => {
if (!_placeSelected) {
SelectedPlace = _selectedPlace;
}
else {
_placeSelected = false;
}
});
This way RaisePropertyChanged("SelectedPlace"); will be called in both cases.
Try this:
<ListBox ItemsSource="{Binding Places}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<i:InvokeCommandAction Command="{Binding ListBoxClick}"
CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType={
x:Type ListBox}}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
(...)
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If that doesn't work, try changing the Binding to this:
CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource Self}}"
UPDATE >>>
Oh sorry, I didn't see that you were using Windows Phone 7. As an alternative, try adding a property into your code behind/view model that binds to the ListBox.SelectedItem property:
<ListBox ItemsSource="{Binding Places}" SelectedItem="{Binding SelectedItem}" ... />
Then you should be able to do this:
ListBoxClick = new RelayCommand(() => {
SelectedPlace = SelectedItem;
});
UPDATE 2 >>>
I don't know if Windows Phone 7 supports the Binding.ElementName property, but if it does, try this:
<ListBox Name="ListBox" ItemsSource="{Binding Places}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<i:InvokeCommandAction Command="{Binding ListBoxClick}"
CommandParameter="{Binding SelectedItem, ElementNameListBox}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
(...)
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>