Turns out turning on string formatting for the binding fixes the caret position problem.
What was:
textbox->DataBindings->Add("Text", model_object, "MyProperty", false,
DataSourceUpdateMode::OnPropertyChanged);
becomes:
textbox->DataBindings->Add("Text", model_object, "MyProperty", true,
DataSourceUpdateMode::OnPropertyChanged);
and like magic, the caret stops repositioning itself. If anyone can comment and explain why this makes sense, please do!
This MSDN forum post provided the hint to try turning on string formatting.