I have implemented the prism MVVM pattern in my desktop WPF non-silverlight application. During the screen loading, I am populating a listbox with a collection of values. This listbox is bound to the ViewModel ( which is my DataContext ) and each item is rendered using a DataTemplate. This is working fine. I am then trying to create a textbox that will allow the user to filter down which records are displayed when they type into it. My natural thought was to go after the KeyUp or TextChanged events, but it turns out that this is more difficult than just binding to the event if trying to maintain the use of ICommand as recommended. I could not find an easy way around this problem and did not want to spend anymore time figuring it out as I have a deadline fast approaching. With that in mind, I attempted the following solution:
XAML:
<TextBox Name="ChannelSearch" Text="{Binding Path=ChannelFilter, Mode=TwoWay}" TextChanged="ChannelSearch_TextChanged" />
Code-Behind:
private void ChannelSearch_TextChanged(object sender, TextChangedEventArgs e) {
var vm = ((IExpressionEditorViewViewModel)ViewModel);
if (vm.FilterChannels.CanExecute())
vm.FilterChannels.Execute();
}
ViewModel:
//In the constructor:
FilterChannels = new DelegateCommand(doFilterChannels, doCanFilterChannels);
//Class properties:
public string ChannelFilter { get; set; }
//Methods used by DelegateCommand:
private void doFilterChannels(){
if (string.IsNullOrWhiteSpace(ChannelFilter))
this.IdFileRows = _allIdFileRows;
else{
var lower = ChannelFilter.Trim().ToLower();
this.IdFileRows = _allIdFileRows.Where(
r => (DisplayChannel && r.A_RowChannelNum.ToLower().Contains(lower))
|| (DisplayMnemonic && r.B_Mnemonic.ToLower().Contains(lower))
|| (DisplayDescription && r.F_Description.ToLower().Contains(lower))
).ToList();
}
}
private bool doCanFilterChannels() {
return true;
}
So with all of that in place, I started debugging. The results did not differ between KeyUp and TextChanged. When "doFilterChannels" is hit, the ChannelFilter text is null everytime. What starts to boggle my mind is that if I hit a save button I made on the screen which hits a DelegateCommmand directly like so:
<Button Content="Save" Command="{Binding Path=SaveExpression}"></Button>
SaveExpression = new DelegateCommand(doSaveExpression, doCanSaveExpression);
private void doSaveExpression() {
Result result = new Result();
try {
result.Success = true;
}
catch (Exception e) {
result.ResultMessages.Add(new ResultMessage { ErrorCode = "500", Message = e.ToString() });
}
result.ThrowErrors();
}
private bool doCanSaveExpression() {
return true; //TODO validation
}
When I break inside the doSaveExpression method and check ChannelFilter, the value is there and accurate. Why is this happening here and not when the KeyUp/TextChanged events are fired? Is there a better way to handle these situations?