SelectedItem 不在 WPF 的 ListView 中绑定

SelectedItem doesn't bind in ListView in WPF

我一直在努力Bind这两个ListViewsViewModel。两个列表都正确加载了项目。但令我惊讶的是,我遇到了一个小问题。

第一个 ListViewSelectedItem 绑定正确,但第二个不绑定!如下图所示。可能是什么原因?

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));
            }
        }
    }
}

绑定实际上工作正常:)

但是,object 的默认比较器会进行 reference 比较。这意味着当它试图在列表中查找现有对象时,它不会选择其中任何一个,因为它们不是同一个实例(根据您的评论)。

解决方案是覆盖 Object.Equals(当您覆盖它时,您还应该覆盖 Object.GetHashCode)。它应该根据对象的一些独特 属性 来测试相等性,这样你就不会得到误报。