Reputation: 5444
I've been trying to Bind
the two ListViews
to ViewModel
. Both lists are loading the items properly. But to my surprise I've encountered a little problem.
The first ListView
's SelectedItem
binds correctly but the second one doesn't bind! As shown in the image below. What could be the reason?
XAML:
<Window x:Class="Test.Dialogs.BeamElevationsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:Test.Dialogs.Converters"
Title="Select Beam Elevation" Height="350" Width="460"
Style="{StaticResource DialogStyle}"
WindowStartupLocation="CenterScreen">
<Window.Resources>
<converters:ElevationValueConverter x:Key="ElevationValueConverter"/>
</Window.Resources>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<GroupBox>
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="175"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="215"/>
</Grid.ColumnDefinitions>
<GroupBox Header="Typs">
<ListView ItemsSource="{Binding TypIds}"
SelectedItem="{Binding CurrentTypId}">
<ListView.View>
<GridView AllowsColumnReorder="False"
ColumnHeaderContainerStyle="{StaticResource DialogsGridViewColumnHeaderStyle}" >
<GridViewColumn Header="Typ."/>
</GridView>
</ListView.View>
</ListView>
</GroupBox>
<GroupBox Grid.Row="0" Grid.Column="2" Header="Elevations">
<ListView ItemsSource="{Binding Elevations}"
SelectedItem="{Binding CurrentBeamElevation}">
<ListView.View>
<GridView AllowsColumnReorder="False"
ColumnHeaderContainerStyle="{StaticResource DialogsGridViewColumnHeaderStyle}" >
<GridViewColumn Header="Typ." />
</GridView>
</ListView.View>
</ListView>
</GroupBox>
</Grid>
</GroupBox>
<Grid Grid.Row="1">
<Button Content="OK"/>
</Grid>
</Grid>
</Window>
Code-Behind:
public partial class BeamElevationsWindow
{
private BeamElevationsViewModel ViewModel { get; set; }
public BeamElevationsWindow()
{
InitializeComponent();
ViewModel = new BeamElevationsViewModel();
DataContext = ViewModel;
}
}
ViewModel:
namespace Test.Dialogs.ViewModels
{
public class BeamElevationsViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public BeamElevationsViewModel()
{
var frames = Building.Frames
.GroupBy(f => f.TypId)
.Select(group => group.First())
.OrderBy(f => f.TypId)
.ToList();
typIds = new List<int>();
foreach (var frame in frames)
{
typIds.Add(frame.TypId);
}
TypIds = typIds;
CurrentTypId = Building.CurrentFrame.TypId;
GetElevations(CurrentTypId);
CurrentBeamElevation = Building.CurrentBeamElevation;
}
public void GetElevations(int typId)
{
var frames = Building.Frames
.Where(f => f.TypId == typId)
.OrderByDescending(f => f.Elevation)
.ToList();
elevations = new List<Elevation>();
foreach (var fr in frames)
{
foreach (var elevation in Building.Elevations)
{
if (Math.Abs(fr.Elevation - elevation.El) < Arithmetics.Tolerance)
{
elevations.Add(elevation);
break;
}
}
}
Elevations = elevations;
}
private List<int> typIds;
public List<int> TypIds
{
get { return typIds; }
private set
{
typIds = value;
RaisePropertyChanged("TypIds");
}
}
private int currentTypId;
public int CurrentTypId
{
get { return currentTypId; }
private set
{
currentTypId = value;
RaisePropertyChanged("CurrentTypId");
}
}
private List<Elevation> elevations;
public List<Elevation> Elevations
{
get { return elevations; }
private set
{
elevations = value;
RaisePropertyChanged("Elevations");
}
}
private Elevation currentBeamElevation;
public Elevation CurrentBeamElevation
{
get { return currentBeamElevation; }
private set
{
currentBeamElevation = value;
RaisePropertyChanged("CurrentBeamElevation");
}
}
private void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
Upvotes: 3
Views: 1102
Reputation: 61349
The binding is actually working fine :)
However, the default comparer for object
does a reference comparison. That means that when its trying to find the existing object in the list, it doesn't pick any of them because they aren't the same instance (per your comment).
The solution is to override Object.Equals
(and when you override that, you should also override Object.GetHashCode
). It should test equality based on some unique property of the object, so you don't get false positives.
Upvotes: 4