If your grid is the only choice, I suggest you use CollectionView as the ItemsSource instead of the actual ObservableCollection. Then, make sure Datagrid.IsSynchronizedWithCurrentItem is set to true. Finally, at the end of your “element logic replacement”, simply move the CollectionView CurrentItem to the corresponding new element.
Below is a sample demonstrating this. (I use ListBox here. Hope it works fine with your Datagrid).
EDIT - A NEW SAMPLE FOR USING MVVM:
Xaml
<Window x:Class="ContextTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="window" Title="MainWindow" Height="350" Width="525"> <DockPanel> <ListBox x:Name="lb" DockPanel.Dock="Left" Width="200" ItemsSource="{Binding ModelCollectionView}" SelectionMode="Single" IsSynchronizedWithCurrentItem="True"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Path=Name}"/> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <TextBlock Text="{Binding ElementName=lb, Path=SelectedItem.Description}"/> </DockPanel> </Window>
Code-Behind:
using System; using System.Windows; using System.Windows.Data; using System.Collections.ObjectModel; using System.Windows.Threading; namespace ContextTest { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.DataContext = new ViewModel(); } } public class ViewModel { private DataGenerator dataGenerator; private ObservableCollection<Model> modelCollection; public ListCollectionView ModelCollectionView { get; private set; } public ViewModel() { modelCollection = new ObservableCollection<Model>(); ModelCollectionView = new ListCollectionView(modelCollection); //Create models for (int i = 0; i < 20; i++) modelCollection.Add(new Model() { Name = "Model" + i.ToString(), Description = "Description for Model" + i.ToString() }); this.dataGenerator = new DataGenerator(this); } public void Replace(Model oldModel, Model newModel) { int curIndex = ModelCollectionView.CurrentPosition; int n = modelCollection.IndexOf(oldModel); this.modelCollection[n] = newModel; ModelCollectionView.MoveCurrentToPosition(curIndex); } } public class Model { public string Name { get; set; } public string Description { get; set; } } public class DataGenerator { private ViewModel vm; private DispatcherTimer timer; int ctr = 0; public DataGenerator(ViewModel vm) { this.vm = vm; timer = new DispatcherTimer(TimeSpan.FromSeconds(5), DispatcherPriority.Normal, OnTimerTick, Dispatcher.CurrentDispatcher); } public void OnTimerTick(object sender, EventArgs e) { Random r = new Random(); //Update several Model items in the ViewModel int times = r.Next(vm.ModelCollectionView.Count - 1); for (int i = 0; i < times; i++) { Model newModel = new Model() { Name = "NewModel" + ctr.ToString(), Description = "Description for NewModel" + ctr.ToString() }; ctr++; //Replace a random item in VM with a new one. int n = r.Next(times); vm.Replace(vm.ModelCollectionView.GetItemAt(n) as Model, newModel); } } } }
OLD SAMPLE:
XAML:
<Window x:Class="ContextTest.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> <ListBox x:Name="lb" SelectionMode="Single" IsSynchronizedWithCurrentItem="True" SelectionMode="Multiple"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Path=Name}"/> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <TextBlock Text="{Binding ElementName=lb, Path=SelectedItem.Name}"/> <Button Click="Button_Click">Replace</Button> </StackPanel> </Window>
Code for:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Collections.ObjectModel; using System.ComponentModel; namespace ContextTest {
Asanch
source share