EventTrigger not working inside ItemsControl in MVVM - silverlight

I want to bind multiple buttons dynamically in MVVM.
1.I Dynamically created buttons using ItemControl
2. It did not Invoke Trigger Click Event.
Please help me on this.
<ItemsControl ItemsSource="{Binding ComponentList,Mode=TwoWay}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Tag="{Binding WorkFlowCompId}">
<Button.Content>
<TextBlock Text="{Binding ComponentName,Mode=TwoWay}"/>
</Button.Content>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding ComponentSelected}"
CommandParameter="{Binding WorkFlowCompId,Mode=TwoWay}" >
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Your problem is that the command is getting the context from its template and there it cannot access the root of the ViewModel. Add this class to your solution:
public class DataContextProxy : FrameworkElement
{
public DataContextProxy()
{
this.Loaded += new RoutedEventHandler(DataContextProxyLoaded);
}
void DataContextProxyLoaded(object sender, RoutedEventArgs e)
{
Binding binding = new Binding();
if (!String.IsNullOrEmpty(BindingPropertyName))
{
binding.Path = new PropertyPath(BindingPropertyName);
}
binding.Source = this.DataContext;
binding.Mode = BindingMode;
this.SetBinding(DataContextProxy.DataSourceProperty, binding);
}
public Object DataSource
{
get { return (Object)GetValue(DataSourceProperty); }
set { SetValue(DataSourceProperty, value); }
}
public static readonly DependencyProperty DataSourceProperty =
DependencyProperty.Register("DataSource", typeof(Object), typeof(DataContextProxy), null);
public string BindingPropertyName { get; set; }
public BindingMode BindingMode { get; set; }
}
then use it in you XAML like so:
<UserControl.Resources>
<library:DataContextProxy x:Key="DataContextProxy"/>
</UserControl.Resources>
Then in your command binding:
<Button Tag="{Binding WorkFlowCompId}">
<Button.Content>
<TextBlock Text="{Binding ComponentName,Mode=TwoWay}"/>
</Button.Content>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding DataSource.ComponentSelected, Source={StaticResource DataContextProxy}"
CommandParameter="{Binding WorkFlowCompId,Mode=TwoWay}" >
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>

A first pass at what you Xaml should look like:-
<ItemsControl ItemsSource="{Binding ComponentList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="{Binding SelectComponent}">
<TextBlock Text="{Binding ComponentName}"/>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I suspect as Derek alludes to in his comment you have a ComponentSelected command on the container. However you should move this command ot the view model for the component. Note I've also renamed it to SelectComponent so that is sounds like an action rather than a property.
TwoWay binding has been removed it wouldn't be doing anything in this case. Assigning a Tag value from a simple binding should be setting off alarm bells that the design is having some problems.
BTW, since you are doing a form of selection would not a ListBox be more appropriate in this case?

Related

InvokeCommandAction not calling

I have a combobox and I need a command in my view model to bind to its ContextMenuOpening event. I've tried referencing System.Windows.Interactivity and using InvokeCommandAction, but the command is not calling. Does anyone see where I'm going wrong?
<ComboBox x:Name="comboBoxAs" Grid.Column="0" VerticalAlignment="Top" Margin="928,62,0,0" Height="25"
ItemsSource="{Binding Source={StaticResource sas}}"
SelectedItem="{Binding Path=as, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource ComboBoxDefault}" HorizontalAlignment="Left" Width="212" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="ContextMenuOpening">
<i:InvokeCommandAction Command="{Binding ContextMenuOpeningCommand, Mode=OneWay}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
ViewModel:
public ICommand ContextMenuOpeningCommand
{
get
{
if (_contextMenuOpeningCommand == null)
{
_contextMenuOpeningCommand = new RelayCommand<object>(param => this.ContextMenuOpening(),
null);
}
return _contextMenuOpeningCommand;
}
}
public void ContextMenuOpening()
{
System.Windows.MessageBox.Show("test", "test");
}
private ICommand _contextMenuOpeningCommand;
Please try DropDownOpened to see whether the command gets hit. I tried it and it works here. Hope this helps :)

Bind DoubleClick Command from DataGrid Row to VM

I have a Datagrid and don't like my workaround to fire a double click command on my viewmodel for the clicked (aka selected) row.
View:
<DataGrid EnableRowVirtualization="True"
ItemsSource="{Binding SearchItems}"
SelectedItem="{Binding SelectedItem}"
SelectionMode="Single"
SelectionUnit="FullRow">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<cmd:EventToCommand Command="{Binding MouseDoubleClickCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
...
</DataGrid>
ViewModel:
public ICommand MouseDoubleClickCommand
{
get
{
if (mouseDoubleClickCommand == null)
{
mouseDoubleClickCommand = new RelayCommand<MouseButtonEventArgs>(
args =>
{
var sender = args.OriginalSource as DependencyObject;
if (sender == null)
{
return;
}
var ancestor = VisualTreeHelpers.FindAncestor<DataGridRow>(sender);
if (ancestor != null)
{
MessengerInstance.Send(new FindDetailsMessage(this, SelectedItem.Name, false));
}
}
);
}
return mouseDoubleClickCommand;
}
}
I want to get rid of the view related code (the one with the dependency object and the visual tree helper) in my view model, as this breaks testability somehow. But on the other hand this way I avoid that something happens when the user doesn't click on a row but on the header for example.
PS: I tried having a look at attached behaviors, but I cannot download from Skydrive at work, so a 'built in' solution would be best.
Why don't you simply use the CommandParameter?
<DataGrid x:Name="myGrd"
ItemsSource="{Binding SearchItems}"
SelectedItem="{Binding SelectedItem}"
SelectionMode="Single"
SelectionUnit="FullRow">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<cmd:EventToCommand Command="{Binding MouseDoubleClickCommand}"
CommandParameter="{Binding ElementName=myGrd, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
...
</DataGrid>
Your command is something like this:
public ICommand MouseDoubleClickCommand
{
get
{
if (mouseDoubleClickCommand == null)
{
mouseDoubleClickCommand = new RelayCommand<SearchItem>(
item =>
{
var selectedItem = item;
});
}
return mouseDoubleClickCommand;
}
}
EDIT: I now use this instead of Interaction.Triggers:
<DataGrid.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick"
Command="{Binding Path=MouseDoubleClickCommand}"
CommandParameter="{Binding ElementName=myGrd, Path=SelectedItem}" />
</DataGrid.InputBindings>
Here is how you could implement it using an attached behaviour:
EDIT: Now registers behaviour on DataGridRow rather than DataGrid so that DataGridHeader clicks are ignored.
Behaviour:
public class Behaviours
{
public static DependencyProperty DoubleClickCommandProperty =
DependencyProperty.RegisterAttached("DoubleClickCommand", typeof(ICommand), typeof(Behaviours),
new PropertyMetadata(DoubleClick_PropertyChanged));
public static void SetDoubleClickCommand(UIElement element, ICommand value)
{
element.SetValue(DoubleClickCommandProperty, value);
}
public static ICommand GetDoubleClickCommand(UIElement element)
{
return (ICommand)element.GetValue(DoubleClickCommandProperty);
}
private static void DoubleClick_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var row = d as DataGridRow;
if (row == null) return;
if (e.NewValue != null)
{
row.AddHandler(DataGridRow.MouseDoubleClickEvent, new RoutedEventHandler(DataGrid_MouseDoubleClick));
}
else
{
row.RemoveHandler(DataGridRow.MouseDoubleClickEvent, new RoutedEventHandler(DataGrid_MouseDoubleClick));
}
}
private static void DataGrid_MouseDoubleClick(object sender, RoutedEventArgs e)
{
var row= sender as DataGridRow;
if (row!= null)
{
var cmd = GetDoubleClickCommand(row);
if (cmd.CanExecute(row.Item))
cmd.Execute(row.Item);
}
}
}
Xaml:
<DataGrid x:Name="grid" EnableRowVirtualization="True"
SelectedItem="{Binding SelectedItem}"
SelectionMode="Single"
SelectionUnit="FullRow" ItemsSource="{Binding SearchItems}">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Behaviours.DoubleClickCommand" Value="{Binding ElementName=grid, Path=DataContext.SortStateCommand}"/>
</Style>
</DataGrid.RowStyle>
You will then need to modify your MouseDoubleClickCommand to remove the MouseButtonEventArgs parameter and replace it with your SelectedItem type.
Way simpler than any of the proposed solutions here.
I'm using this one.
<!--
requires IsSynchronizedWithCurrentItem
for more info on virtualization/perf https://stackoverflow.com/questions/9949358/datagrid-row-virtualization-display-issue
-->
<DataGrid ItemsSource="{Binding SearchItems}"
IsSynchronizedWithCurrentItem="True"
AutoGenerateColumns="false" CanUserAddRows="False" CanUserDeleteRows="False" IsReadOnly="True" EnableRowVirtualization="True"
>
<!-- for details on ICollection view (the magic behind {Binding Accounts/} https://marlongrech.wordpress.com/2008/11/22/icollectionview-explained/ -->
<DataGrid.InputBindings>
<MouseBinding
MouseAction="LeftDoubleClick"
Command="{Binding MouseDoubleClickCommand}"
CommandParameter="{Binding SearchItems/}" />
</DataGrid.InputBindings>
</DataGrid>
from WPF DataGrid: CommandBinding to a double click instead of using Events
You may try this workaround:
<DataGrid EnableRowVirtualization="True"
ItemsSource="{Binding SearchItems}"
SelectedItem="{Binding SelectedItem}"
SelectionMode="Single"
SelectionUnit="FullRow">
<DataGrid.Columns>
<DataGridTemplateColumn Header=".....">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock .....>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<cmd:EventToCommand Command="{Binding MouseDoubleClickCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</DataTemplate>
...................
In this case you have to specify DataTemplate for each column in the DataGrid

How to subscribe event in datatemplate of listview

In WPF I have a listview that is bound to an ObservableCollection.
XAML:
<ListView Name="listView" DockPanel.Dock="Top" ItemsSource="{Binding Path=ListOfOldData}" SelectedItem="{Binding Path=SelectedOldData, Mode=TwoWay}" SelectionMode="Single">
<ListView.ContextMenu>
<ContextMenu>
<Button Content="Load" Command="{Binding Path=LoadCommand}" Name="loadButton" Height="23" Width="75" DockPanel.Dock="Left"/>
<!-- Is working just fine -->
</ContextMenu>
</ListView.ContextMenu>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock MouseLeftButtonDown="TextBlock_MouseLeftButtonDown"
Text="{Binding Path=Name}" FontWeight="Bold"><TextBlock Text=" - " FontWeight="Normal"/><TextBlock Text="{Binding Path=UpdateDatum}" FontWeight="Normal"/></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
What I actually wanted to receive is a double-click on the selected-item. As I can't bind a command to a textblock in xaml (can I?) I tried doing this via the MouseLeftButtonDown-Event. But the event is never received!
C# (in code behind):
private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Console.WriteLine("MouseLeftButtonDown received!");
}
What am I doing wrong? How can I receive the event? Btw.: The command of the contextmenu is working just fine :)
UPDATE I found my error --> I added the event in the wrong usercontrol. Damn my missing concentration. Sorry for bugging you all.
you can simply use InvokeCommandAction from blend sdk (System.Windows.Interactivity.dll)
<ListView x:Name="lvw" ItemsSource="{Binding ListOfOldData}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding Path=OpenCommand}"
CommandParameter="{Binding ElementName=lvw, Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListView>
EDIT:
viewmodel should look something like this:
public List<object> ListOfOldData{ get; set; }
private DelegateCommand<object> _openCommand;//or RelayCommand
public DelegateCommand<object> OpenCommand
{
get { return _openCommand?? (this._openCommand= new DelegateCommand<object>(this.Execute)); }
}
private void Execute(object obj)
{
//obj is your selectedItem
}
ps: dunno your type thats why object
The ListView has a DoubleClick MouseEvent.
This should do it :
<ListView MouseDoubleClick="DoubleClickOnIt">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold">
<TextBlock Text=" - " FontWeight="Normal"/>
<TextBlock Text="{Binding Path=UpdateDatum}" FontWeight="Normal"/>
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
<ListViewItem>
dddd
</ListViewItem>
<ListViewItem>
eeeee
</ListViewItem>
</ListView>
And the code behind :
private void DoubleClickOnIt(object sender, MouseButtonEventArgs e)
{
var listView = sender as ListView;
var selectedItem = listView.SelectedItem;
Console.WriteLine("received!");
}

MVVM-Light, firing events from a button inside a data grid column template

MVVM light has been a pleasure to learn, but here I am stuck. The problem is event firing.
In the code below, one button the works and fires events. The other button doesnt. No binding errors are reported in the output. Is there anything obvious I am missing?
<Grid x:Name="LayoutRoot">...
<StackPanel>
<Button Content="THIS BUTTON WORKS">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<Command:EventToCommand Command="{Binding DataContext.HandleAddQuestionActionCommand, ElementName=LayoutRoot, Mode=OneWay}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<sdk1:DataGrid ItemsSource="{Binding QuestionActions}" AutoGenerateColumns="False" >
<sdk1:DataGrid.Columns>
<sdk1:DataGridTextColumn Binding="{Binding Answer.Name}" Header="Answer"/>
<sdk1:DataGridTemplateColumn Header="Edit">
<sdk1:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="THIS BUTTON DONT WORK" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<Command:EventToCommand Command="{Binding DataContext.HandleEditQuestionActionCommand, ElementName=LayoutRoot, Mode=OneWay}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DataTemplate>
</sdk1:DataGridTemplateColumn.CellTemplate>
</sdk1:DataGridTemplateColumn>
</sdk1:DataGrid.Columns>
</sdk1:DataGrid>
</StackPanel>
ViewModel code:
public RelayCommand<RoutedEventArgs> HandleAddQuestionActionCommand {
get; private set;
}
public RelayCommand<RoutedEventArgs> HandleEditQuestionActionCommand {
get; private set;
}
HandleAddQuestionActionCommand = new RelayCommand<RoutedEventArgs>(e =>{...});
HandleEditQuestionActionCommand = new RelayCommand<RoutedEventArgs>(e =>{...});
Your data context is lost in the DataGrid DataGridTemplateColumn since the DataGrid.Columns isn't a dependency property. Because of this, you can't use element-to-element data binding from within your DataGridTemplateColumn.
However, this is easily fixed thanks to MVVM Light Toolkit's ViewModelLocator.
I don't know what your ViewModel is called, but assuming it is MainViewModel you can change your button binding to this:
<sdk1:DataGridTemplateColumn Header="Edit">
<sdk1:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="THIS BUTTON WILL WORK NOW ;-)" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<Command:EventToCommand Command="{Binding Source={StaticResource Locator},
Path=MainViewModel.HandleEditQuestionActionCommand}"
PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DataTemplate>
</sdk1:DataGridTemplateColumn.CellTemplate>
</sdk1:DataGridTemplateColumn>
The button inside the DataGrid has a DataContext of QuestActions since the Binding is based on the the DataGrid's ItemSource Property. That being the case, you'll need to find the DataContext of the DataGrid itself (or the UserControl or whatever parent that has the Command in it's DataContext) to get to your Command:
<Command:EventToCommand
Command="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type sdk1:DataGrid}},
Path=DataContext.ViewSchemaCommand, Mode=OneWay}"
PassEventArgsToCommand="True" />
This solution only works for static view models. check out Dan Whalin's page out for an alternative answer. http://weblogs.asp.net/dwahlin/archive/2009/08/20/creating-a-silverlight-datacontext-proxy-to-simplify-data-binding-in-nested-controls.aspx
You can create a resource like so (don't forget your reference):
<UserControl.Resources>
<controls:DataContextProxy x:Key="DataContextProxy" />
</UserControl.Resources>
or
<sdk:Page.Resources>
<controls:DataContextProxy x:Key="DataContextProxy"/>
</sdk:Page.Resources>
Use in control like so:
<sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Content">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cmd:EventToCommand Command="{Binding Source={StaticResource DataContextProxy}, Path=DataSource.MyCommand}"
CommandParameter="{Binding Path=SomeValue}"
PassEventArgsToCommand="False">
</cmd:EventToCommand>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
ViewModel
Define RelayCommand:
public RelayCommand<object> MyCommand { get; set; }
Set RelayCommand in Constructor:
MyCommand = new RelayCommand<object>((e) =>
{
if (e != null && e is int)
{
int varName = int.Parse(e.ToString());
//DoSomething...
}
});

MVVM Light is too fast :)

I have a simple WM7 Page with a TextBox. Futher, I assigned EventToCommand (a RelayCommand<string>) to this TextBox, reacting to the TextChanged event. For testing pourposes I made additional method TextBox_TextChanged in the page's code behind. Both the command and TextBox_TextChanged print a message box with the textbox content.
Initial value of the TextBox is "ABC". Then I press D and:
TextBox_TextChanged prints ABCD.
The command prints ABC. D is missing.
Why is the command so fast?
Command declaration:
public RelayCommand<string> TextChanged {get; private set;}
Command initialization:
TextChanged = new RelayCommand<string>((s) => MessageBox.Show(s));
Command binding:
<TextBox x:Name="SearchTextBox" Margin="10,0" TextWrapping="Wrap" Text="{Binding SearchString, Mode=TwoWay}" FontStyle="Italic" TextChanged="SearchTextBox_TextChanged" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding TextChanged, Mode=OneWay}" CommandParameter="{Binding Text, ElementName=SearchTextBox}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
I can't reproduce this behaviour. I have tried using EventToCommand and a Behaviour(which simply listens to TextChanged event).
Without seeing the code I suspect this might be to do with how you get the text of the search box or a logic error elsewhere.
This is a snippet of how I use EventToCommand:
<TextBox Name="SearchTextBox">
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<cmd:EventToCommand Command="{Binding TestTextChangedCommand,Mode=OneWay}" CommandParameter="{Binding Path=Text, ElementName=SearchTextBox}"/>
</i:EventTrigger>
<i:Interaction.Triggers>
</TextBox>
In the viewmodel
m_TestTextChangedCommand = new RelayCommand<string>(val => System.Diagnostics.Debug.WriteLine(val));
As you can see I used a commandparameter to pass the value of the textbox to the viewmodel. This way the viewmodel doesn't have to know about the textbox to get the text value.
An alternative to this approach would be to use behaviours and TwoWay binding to update a property:
<TextBox Name="SearchTextBox" Text="{Binding TextInViewModel, Mode=TwoWay}" >
<i:Interaction.Behaviors>
<sc:UpdateOnTextChangedBehavior/>
</i:Interaction.Behaviors>
</TextBox>
UpdateOnTextChangedBehavior class:
public class UpdateOnTextChangedBehavior : Behavior<TextBox>
{
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.TextChanged +=
new TextChangedEventHandler(AssociatedObject_TextChanged);
}
void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
{
System.Diagnostics.Debug.WriteLine(((TextBox)sender).Text);
BindingExpression binding =
this.AssociatedObject.GetBindingExpression(TextBox.TextProperty);
if (binding != null)
{
binding.UpdateSource();
}
}
protected override void OnDetaching()
{
base.OnDetaching();
this.AssociatedObject.TextChanged -=
new TextChangedEventHandler(AssociatedObject_TextChanged);
}
}
What the above does is mimick the behaviour of desktop WPF Binding with UpdateSourceTrigger=PropertyChanged, which is missing in Silverlight. So what will happen, whenever you type into the text box TextInViewModel property will get updated. This property doesn't haven to be a DependencyProperty, it could just be a normal CLR property.
This works with TextBox via parameter for RelayCommand. IOW - RelayCommand<TextBox>
<TextBox Height="72" HorizontalAlignment="Left" Margin="8,136,0,0" Name="txtFilter" Text="" VerticalAlignment="Top" Width="460" >
<interactivity:Interaction.Triggers>
<interactivity:EventTrigger EventName="TextChanged">
<cmd:EventToCommand Command="{Binding SearchedTextChanged}" CommandParameter="{Binding ElementName=txtFilter}" />
</interactivity:EventTrigger>
</interactivity:Interaction.Triggers>
</TextBox>
public RelayCommand<TextBox> SearchedTextChanged { get; set; }
SearchedTextChanged = new RelayCommand<TextBox>(OnSearchedTextChanged);
private void OnSearchedTextChanged(TextBox val)
{
if (val != null)
{
System.Diagnostics.Debug.WriteLine(val.Text);
}
}
I had a similar issue and found that the databinding operation does not always fire until the TextBox loses focus. However, the Command will fire immediately.
If you want to guarantee that the databinding has occurred before you use the value, you can call the BindingExpression.UpdateSource() method on your control. Try something like this:
var bindTarget = SearchTextBox.GetBindingExpression(TextBox.TextProperty);
bindTarget.UpdateSource();
To avoid referring to your TextBox directly in your ViewModel (as you should with MVVM), you can use FocusManager.GetFocusedElement(). This is particularly useful when dealing with ApplicationBar buttons as they don't seem to receive focus when used.
Some code I sued (similar to yours Command example):
Command declaration:
public RelayCommand<string> TextChanged {get; private set;}
Command initialization:
TextChanged = new RelayCommand<string>((s) => MessageBox.Show(s));
Command binding:
<TextBox x:Name="SearchTextBox" Margin="10,0" TextWrapping="Wrap" Text="{Binding SearchString, Mode=TwoWay}" FontStyle="Italic" TextChanged="SearchTextBox_TextChanged" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding TextChanged, Mode=OneWay}" CommandParameter="{Binding Text, ElementName=SearchTextBox}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
For some reasons messagebox shows a string with one character delay.

Resources