Event firing before databinding is updated - how do I wait for the update? - wpf

I'm currently encountering this issue while programming Metro, but I'm sure it applies to WPF, Silverlight and possibly even WinForms.
I have a databound TextBox and a method attached to the LostFocus event of the TextBox. When it loses focus, I want the code behind to trigger a save function in order to persist the data. The problem is that the LostFocus-event triggers before the business object is updated from the GUI through TwoWay databinding.
What is the best way to handle this? Is there some way to force update of the databinding from the LostFocus method (would probably be platform-specific)?

It sounds like you're wanting to do some business logic instead of having the GUI update the textbox. I would set the Textbox to only be BindingMode.OneWay, so that when the business object is changed the textbox is updated properly.
Then in the Lostfocus event (again wpf, but I think you'll get the idea):
private void EditBoxLostFocus( object sender, KeyboardFocusChangedEventArgs e )
{
var textbox = sender as TextBox;
//update your business object w/ textbox.Text value
//other business logic
}
This way you're in full control of when the object gets updated, and can apply your business rules.

Set UpdateSourceTrigger = PropertyChanged on the TextBox binding.
http://msdn.microsoft.com/en-us/library/system.windows.data.updatesourcetrigger(v=vs.100).aspx

Related

MVVM pattern - executing view operations

I'm using MVVM Pattern (with MVVM Light) to build my XAML app (win8). I have a ListView, which is bound to a property of my ViewModel. I also have a button that triggers an operation on that ViewModel, which updates that property (which results in updating the ListView). The button uses commanding to execute the operation on the ViewModel. So far so good.
The problem is that after the list is refreshed I need to perform an operation that strictly belongs to my View, not to the ViewModel. It should scroll the list to a specific item. How to trigger that operation? Should I use a specific ListView event?
Using an EventHandler and the ScrollIntoView(Object) method you can achieve what you want without using references of the View inside the ViewMovel and respecting MVVM pattern.
Create an event in your ViewModel like this:
public event EventHandler ScrollListView;
In your View add a callback to scroll the ListView when the property is updated:
ViewModel vm;
vm.ScrollListView += (sender, e) =>
{
var specificItem = **some item**;
MyListView.SelectedItem = specificItem;
MyListView.UpdateLayout();
MyListView.ScrollIntoView(MyListView.SelectedItem);
};
Then in your ViewModel when you update that property and want to scroll the ListView:
if (this.ScrollListView != null)
{
this.ScrollListView(this, EventArgs.Empty);
}
This is how I usually do with some tweaks for each case of course.
The ViewModel is there to decouple the UI Code from the UI Design (E.g. XAML). [Separation of Concerns of Designer and Developer, Automated testing of UI Code, etc]
Ideally the code-behind file of the View will be empty (except the call to InitializeComponent) and all UI logic and state will be handled by the ViewModel. However, in practice there might be some specific UI manipulation that cannot be handled by data-binding alone and you will need to resort to code. Such code should be placed in the code-behind.
In your case, the logic for (a) when and (b) which item to scroll to must be in the ViewModel (not in the View). Only any additional logic required to perform the actual scrolling in the ListView will be in the View code-behind.
Yes, an event would be the ideal way to do this, to avoid having any references to the View inside the ViewModel. I would recommend however to create a custom event in the ViewModel (e.g. OnFirstItemInViewChanged with arguments the item to scroll to) and in the View code-behind register to this event and just call ListView.ScrollIntoView(item).
Note:
WinForms DataGridView had a property FirstDisplayedScrollingRowIndex. If there was something similar in WPF ListView, you could solve this by binding this property to a ViewModel property, therefore leaving the code-behind completely clean.

wpf: TextChanged event fired on setting DataContext

I've got a simple View with a single textbox that gets databound to a simple ViewModel with a single string property.
I need to catch the TextChanged event of that textbox so that I can do a little validation magic.
The problem that I am running into is that the TextChanged event fires for that textbox when the DataContext is set for the View.
Is there a standard mechanism that I can use to determine if the event is firing because of the DataContext being set versus when the user is making changes?
Thanks!
As far as I know there is no such mechanism. What you should do instead is to do your validation magic using standard means of WPF. Please see the following link: http://msdn.microsoft.com/en-us/library/ms752347.aspx#data_validation.
Anyway, as long as you use MVVM you can always detect that text has changed in the setter of the bound property in your view model.

WPF Calendar: Binding to MVVM commands?

I am wiring up a WPF calendar to an MVVM view model. I'm not sure how to bind date selections and month changes to MVVM ICommand objects. For example to process a selected date change, what object would I bind in XAML to the appropriate command property in my view model?
As nearly as I can tell, I am stuck with event handling in code-behind. For example, it looks like the only way to detect a date selection change is to write a SelectedDatesChanged event handler. I can invoke the command property in my view model from the event handler, like this:
private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
{
var viewModel = (CalendarViewModel) DataContext;
viewModel.GetDateNotes.Execute();
}
But I sense a code smell to that approach, unless there is no better approach available. Can anyone tell me how to bind a WPF Calendar to MVVM commands directly from XAML? Is there a better approach than the one I am taking? Thanks for your help.
Wouldn't you have a DateTime property in your VM that is bound to the calendar and that raises PropertyChanged? If so, can't you watch for property changed internally or write code in your setter so that you know when the view has changed its value?

Silverlight DataBinding Loading Animation

Is there an event somewhere in the Silverlight control model that is raised once an item is databound? I am binding at design time to a large amount of data and would like to display an animation until the databinding is complete.
There is no specific event that is fired when databinding is completed. Your best bet would probably be to key off of the FrameworkElement.LayoutUpdated event. This is the last event in the lifecycle before a control is ready for user interaction. However, this event will continue to be raised many more times due to property changes, size changes, and explicit calls to UpdateLayout() or InvalidateArrange(). Therefore you will have to add some extra logic to make sure that the LayoutUpdated event warrants stopping/hiding your animation, such as only doing it the first time or if you are sure the event was fired due to a change in databinding.
If the control is actually your own custom control and you are binding to custom DependencyProperties on that control then you could raise your own event on the PropertyChangedCallbacks for each of the properties to signal that they have been updated via databinding.
Here's what I do:
private object lastDataContext;
private void MyClass_Loaded(object sender, RoutedEventArgs e)
{
if (DataContext != lastDataContext)
{
perform_onetime_operation();
lastDataContext = DataContext;
}
}
That way perform_onetime_operation will get called not just the first time databinding happens, but any time that the DataContext changes meaning that data is re-bound.

WPF DataGrid how to get when ItemsSource updates

Which event fires when DataGrid's source is updating? I've tried DataContextChanged and SourceUpdated but it never worked out.
Actually I need a simple thing. I want, if there is a new row comes, scroll the GridView's scrollbar down to the bottom to see what it was.
I had the same problem and I manage it this way
DataGrid myGrid = new DataGrid();
CollectionView myCollectionView = (CollectionView)CollectionViewSource.GetDefaultView(myGrid.Items);
((INotifyCollectionChanged)myCollectionView).CollectionChanged += new NotifyCollectionChangedEventHandler(DataGrid_CollectionChanged);
You then need to implement the logic in the event handler DataGrid_CollectionChanged.
Set NotifyOnTargetUpdated = true for the ItemsSource binding and handle TargetUpdated event. If you've multiple bindings, then look for DataTransferEventArgs Property to find out if the target is ItemsSource or not.
If you are trying to have the grid refresh when something is added to the database itself, that's not going to happen. I'm more familiar with WinForms than WPF but I'm assuming there is no magical way to keep a grid in sync with the database without writing some background process that continuously checks for database changes.
If you are updating the actual data source of the grid (ex. Collection) then that will update the grid.
For my part i've used SelectionChange notification which raise each event Del/Add/Edit/Select
It's work very well
private void dataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Console.WriteLine("hi");
}

Resources