【问题标题】:ListView not showing observablecollection, when a new collection is assigned to bound property, even though RaisePropertyChanged is calledListView 不显示 observablecollection,当新集合分配给绑定属性时,即使调用 RaisePropertyChanged
【发布时间】:2016-08-11 22:11:58
【问题描述】:

我有一个绑定到 ObservableCollection 的 ListView。我面临的问题是视图没有更新,当我分配一个新集合时,即使我正在调用RaisePropertyChanged

//TrackIO.GetTracks()
public static ObservableCollection<Track> GetTracks() 
{
     return tracks;
}

    <ListView x:Name="TrackListView" 
                  SelectionMode="Single" 
                  ItemsSource="{Binding Path=ObservableTracks}"
                  SelectedIndex="{Binding SelectedTrackIndex, Mode=TwoWay}"
                  >
        <!-- Column Binding matches track object properties -->
             <ListView.View>
                <GridView>
                    <GridViewColumn Header="Title" Width="600" DisplayMemberBinding="{Binding Title}" />
                    <GridViewColumn Header="Album" Width="350" DisplayMemberBinding="{Binding Album}" />
                    <GridViewColumn Header="Artist" Width="250" DisplayMemberBinding="{Binding Artist}" />
                    <GridViewColumn Header="Duration" Width="200" DisplayMemberBinding="{Binding FormattedDuration}" />
                </GridView>
            </ListView.View>
     </ListView>

    private ObservableCollection<Track> _observableTracks;
    public ObservableCollection<Track> ObservableTracks
    {
        get { return _observableTracks; }
        private set
        {
            _observableTracks = value;
            RaisePropertyChanged();
        }
    }

我正在使用 MVVM 灯来通知视图模型,将属性设置为不同的集合。

如您所见,我在集合中有项目,因此当我将新集合分配给 ObservableTracks 属性时。 RaisePropertyChanged() 应该被调用,但是视图是空的/什么都不显示。

非常感谢任何帮助。谢谢。

【问题讨论】:

    标签: c# wpf mvvm mvvm-light observablecollection


    【解决方案1】:

    需要调用setter 才能调用RaisePropertyChanged 方法。如果它是私有的,则不能从外部代码调用。如果 Resharper 将其标记为未更改状态,则应使用注释忽略它(尽管由于方法调用它不应标记它)。

    private ObservableCollection<Track> _observableTracks;
    public ObservableCollection<Track> ObservableTracks
    {
        get { return _observableTracks; }
        set
        {
            _observableTracks = value;
            RaisePropertyChanged();
        }
    }
    

    此外,在设置之前检查值是否相等是一个很好的模式:

    ...
    set
    {
        if (_observableTracks == value)
        {
            return;
        }
    }
    

    最后,RaisePropertyChanged 使所有属性刷新,您可能只需要单个属性更改通知:

    RaisePropertyChanged(() => ObservableTracks);
    

    【讨论】:

    • 我删除了“ObservableTracks”参数,因为 resharper 显示此消息:参数名称与默认值相同。这不是问题,但感谢您提供帮助。
    • 你是如何实现 INotifyPropertyChanged 接口的?
    • 你为什么要放私人集??
    • 我没有。我正在使用 MVVM 灯光框架。调用 RaisePropertyChanged 会将更新通知绑定到该属性的任何内容。它适用于除此集合之外的所有其他属性。
    • 我的视图模型扩展了 ViewModelBase,根据 MVVM 灯。
    【解决方案2】:

    以下代码在我的机器上运行良好。

    视图模型:

    public class Track
    {
        public string Title { get; set; }
    }
    
    public class MainViewModel : ViewModelBase
    {
        private ObservableCollection<Track> _observableTracks;
    
        public MainViewModel()
        {
            DoSomething = new RelayCommand(() => ObservableTracks = new ObservableCollection<Track>() { new Track { Title = "test" } });
        }
    
        public ObservableCollection<Track> ObservableTracks
        {
            get { return _observableTracks; }
            private set
            {
                _observableTracks = value;
                RaisePropertyChanged();
            }
        }
    
        public RelayCommand DoSomething { get; private set; }
    }
    

    查看:

    <Window.DataContext>
        <local:MainViewModel />
    </Window.DataContext>
    
    <StackPanel>
        <Button Command="{Binding DoSomething}" Content="Do something" />
        <ListView x:Name="TrackListView" 
                  SelectionMode="Single" 
                  ItemsSource="{Binding Path=ObservableTracks}"
                  SelectedIndex="{Binding SelectedTrackIndex, Mode=TwoWay}"
                  >
            <!-- Column Binding matches track object properties -->
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Title" Width="600" DisplayMemberBinding="{Binding Title}" />
                    <GridViewColumn Header="Album" Width="350" DisplayMemberBinding="{Binding Album}" />
                    <GridViewColumn Header="Artist" Width="250" DisplayMemberBinding="{Binding Artist}" />
                    <GridViewColumn Header="Duration" Width="200" DisplayMemberBinding="{Binding FormattedDuration}" />
                </GridView>
            </ListView.View>
        </ListView>
    </StackPanel>
    

    你没有忘记设置视图的DataContext吗?

    如果不能,您能否分享一个失败的简短示例?

    【讨论】:

    • 谢谢。有用。我认为数据上下文是问题所在。 :)
    猜你喜欢
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    • 2016-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-14
    相关资源
    最近更新 更多