I have following Situation. I have a ListView set up as following:
<ListView Margin="3,3,3,3" ItemsSource="{Binding Toner}" SelectedValue="{Binding CurrentToner}" IsSynchronizedWithCurrentItem="True">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="BorderBrush" Value="LightGray" />
<Setter Property="BorderThickness" Value="0,0,0,1" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="{Binding Id}" FontWeight="Bold"></Label>
<Label Grid.Row="0" Grid.Column="1" Content="{Binding Name}" FontWeight="Bold"></Label>
<Label Grid.Row="1" Grid.Column="0" Content="{Binding Ratio}">
</Label>
<Label Grid.Row="1" Grid.Column="1" Content="{Binding TonerType.Name}" ></Label>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I set the Property CurrentToner in the corresponding ViewModel:
private Toner currentToner = new Toner();
public Toner CurrentToner
{
get => currentToner;
set
{
SetProperty(ref currentToner, value);
updateTonerCommand.RaiseCanExecuteChanged();
deleteTonerCommand.RaiseCanExecuteChanged();
increaseAmountCommand.RaiseCanExecuteChanged();
RaisePropertyChanged(nameof(Changes));
}
}
Now in the same View as above i also have some Controls bound to Properties of the CurrentToner.
<TextBox Style="{StaticResource TextBoxStyle}" Grid.Row="0" Grid.Column="1" Text="{Binding CurrentToner.Name}"></TextBox>
<TextBox Style="{StaticResource TextBoxStyle}" Grid.Row="1" Grid.Column="1" Text="{Binding CurrentToner.Level}" ></TextBox>
<ComboBox Grid.Row="2" Grid.Column="1" SelectedValue="{Binding CurrentToner.TonerType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding TonerTypes, Mode=OneWay}" DisplayMemberPath="Name"></ComboBox>
<TextBox Style="{StaticResource TextBoxStyle}" Grid.Column="1" Grid.Row="3" Text="{Binding CurrentToner.Note}" AcceptsReturn="True" VerticalScrollBarVisibility="Visible"></TextBox>
Now i can click arround in the ListView and my TextControls will be updated as they are supposed to. However, if i reload the Data in the Observable Collection, the selected Item will no longer be updated in the Combobox (The data is still available, i checked with the Debugger and the Combobox can still set the TonerType in the CurrentToner) I reload the Data from an SQL Server using Entity Framework :
private void ReloadToner()
{
Toner.Clear();
using (var uw = new UnitOfWork(new Gritly_DEVEntities1()))
{
Toner.AddRange(uw.Toners.GetAll());
}
}
How do i have to implement my Reload logic to update the selected item again? (It works before the reload)
EDIT: Screenshots of how it is supposed to be and how it's not. it should be like this not like this
EDIT2: I found the Answer, I had to override Equals() on TonerType to compare based on Id instead of Adress
If you reload the data then you have new objects in your collection.
I missed what that object type is if it's there but let's call that a Toner anyhow.
Make sure Toner has something uniquely identifies it, like an ID.
If you look at a Toner object , you can probably work out which is the old current one but computers are very literal minded. They need you to tell them exactly how they're supposed to know a Toner is a specific Toner rather than just any old one.
When you're going to re-read your data, save that ID in a private variable.
Read the data.
Build your observable collection.
Find the appropriate entry using some linq matching on id.
Something like:
Toner newSelectedToner = Toners.Where(x=>x.ID = lastSelectedID).FirstOrDefault();
That's just air code by the way.
Set CurrentToner to that instance.
Also, override equals on your Toner to use ID.