将ViewModel中包含的ObservableCollection绑定到ListView

时间:2012-11-27 17:33:54

标签: c# wpf mvvm visual-studio-2012

我进行了搜索和搜索,但无法获得正确有用的答案。

我有一个MainWindow wpf窗口。它的DataContext设置为ViewModel。

我有一个ListView,绑定到ViewModel中的ObservableCollection:

        <ListView Grid.Row="1" Grid.Column="0" Margin="2" Name="sources_ListView" Grid.RowSpan="1" ItemsSource="{Binding Path=Sources}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Width="290" Header="Name"
                                    DisplayMemberBinding="{Binding Path=OriginalPath}"/>
                    <GridViewColumn Width="80" Header="Type" 
                                    DisplayMemberBinding="{Binding Path=Type}"/>
                </GridView>
            </ListView.View>
        </ListView>

RelayCommand:

        public ICommand BrowseFileFolderCommand
        {
            get
            {
                if (_browseFileFolderCommand == null)
                {
                    _browseFileFolderCommand = new RelayCommand(o => 
                               {
                                  _sources.Add(new SourceItem(selectedPath, new DirectoryInfo(selectedPath)));
                               }, null);
                }
                return _browseFileFolderCommand;
            }
        }

现在很明显Lambda函数的作用,在现实世界中不起作用,因为我已经脱离了上下文,但接受了它确实将SourceItem添加到ObservableCollection _sources并且有一个公共源获取的事实_sources。我还使ObservableCollection使用的类型使用了INotifyChangedProperty。

当我使用RelayCommand时,它在一个向ObservableCollection添加源的按钮内,ListView不会更新?

感谢您的帮助

EDIT SourceItem:

public class SourceItem : ISourceItem, INotifyPropertyChanged
{
    DirectoryInfo _sourceFolder;
    public DirectoryInfo SourceFolder { get { return _sourceFolder; } private set { _sourceFolder = value; } }

    FileInfo _sourceFile;
    public FileInfo SourceFiles { get { return _sourceFile; } private set { _sourceFile = value; } }

    string _originalPath;
    public string OriginalPath { get { return _originalPath; } private set { _originalPath = value; OnPropertyChanged("OriginalPath"); } }

    bool _isFolder;
    public bool IsFolder { get { return _isFolder; } }

    // display friendly property of IsFolder
    public string Type { get { return _isFolder == true ? "Folder" : "File"; } }

    public SourceItem(string originalPath, DirectoryInfo sourceFolder)
    {
        _originalPath = originalPath;
        _sourceFolder = sourceFolder;
        _sourceFile = null;

        _isFolder = true;
    }

    public SourceItem(string originalPath, FileInfo sourceFile)
    {
        _originalPath = originalPath;
        _sourceFile = sourceFile;
        _sourceFolder = null;

        _isFolder = false;
    }



    #region INotifyPropertyChanged Members

    /// <summary>
    /// Raised when a property on this object has a new value.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Raises this object's PropertyChanged event.
    /// </summary>
    /// <param name="propertyName">The property that has a new value.</param>
    protected virtual void OnPropertyChanged(string propertyName)
    {
        this.VerifyPropertyName(propertyName);

        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
        }
    }

    #endregion // INotifyPropertyChanged Members

    #region Debugging Aides

    /// <summary>
    /// Warns the developer if this object does not have
    /// a public property with the specified name. This 
    /// method does not exist in a Release build.
    /// </summary>
    [Conditional("DEBUG")]
    [DebuggerStepThrough]
    public void VerifyPropertyName(string propertyName)
    {
        // Verify that the property name matches a real.
        // public, instance property on this object
        if (TypeDescriptor.GetProperties(this)[propertyName] == null)
        {
            string msg = String.Format("Invalid property name: {0}", propertyName);

            if (this.ThrowOnInvalidPropertyName)
                throw new Exception(msg);
            else
                Debug.Fail(msg);
        }
    }

    /// <summary>
    /// Returns whether an exception is thrown, or if a Debug.Fail() is used
    /// when an invalid property name is passed to the VerifyPropertyName method.
    /// The default value is false, but subclasses used by unit tests might 
    /// override this property's getter to return true.
    /// </summary>
    protected virtual bool ThrowOnInvalidPropertyName { get; private set; }

    #endregion
}

1 个答案:

答案 0 :(得分:1)

使用该属性的公共版本添加新项目

Sources.Add(new SourceItem(selectedPath, new DirectoryInfo(selectedPath)));

您当前正在将该项目添加到您的媒体资源的私有版本(_sources),而您的用户界面则绑定到该属性的公开版本(Sources),因此您的用户界面无法获取<{1}}通知属性的私有版本引发,因此不知道它需要更新。

另一种方法是手动为您的类提升CollectionChanged事件,以告知UI更新。这通常是我想要同时向我的集合添加大量项目时所做的,但只有UI更新一次。

PropertyChanged