简体   繁体   English

SelectedItem不在WPF中的ListView中绑定

[英]SelectedItem doesn't bind in ListView in WPF

I've been trying to Bind the two ListViews to ViewModel . 我一直在尝试将两个ListViews BindViewModel 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! 第一个ListViewSelectedItem正确绑定,但第二个不绑定! As shown in the image below. 如下图所示。 What could be the reason? 可能是什么原因?

在此输入图像描述

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

The binding is actually working fine :) 绑定实际上工作正常:)

However, the default comparer for object does a reference comparison. 但是, object的默认比较器会进行参考比较。 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 ). 解决方案是覆盖Object.Equals (当你覆盖它时,你也应该覆盖Object.GetHashCode )。 It should test equality based on some unique property of the object, so you don't get false positives. 它应该根据对象的一些独特属性测试相等性,这样你就不会得到误报。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM