WPF - 如何使用嵌套的ObservableCollection刷新视图

时间:2014-06-06 10:02:47

标签: wpf xaml datagrid observablecollection

DataGridSelectedQueryView.SelectedColumns绑定SelectedQueryView

public QueryViewItem SelectedQueryView { get; set; }

和QueryViewItem是:

public class QueryViewItem : ViewModelBase
{
    private string _viewIcon;
    private string _viewName;
    private string _tableName;

    public string ViewIcon
    {
        [DebuggerStepThrough]
        get { return _viewIcon; }
        [DebuggerStepThrough]
        set
        {
            if (value != _viewIcon)
            {
                _viewIcon = value;
                OnPropertyChanged("ViewIcon");
            }
        }
    }
    public string ViewName
    {
        [DebuggerStepThrough]
        get { return _viewName; }
        [DebuggerStepThrough]
        set
        {
            if (value != _viewName)
            {
                _viewName = value;
                OnPropertyChanged("ViewName");
            }
        }
    }

    public string TableName
    {
        [DebuggerStepThrough]
        get { return _tableName; }
        [DebuggerStepThrough]
        set
        {
            if (value != _tableName)
            {
                _tableName = value;
                OnPropertyChanged("TableName");
            }
        }
    }

    public ObservableCollection<TableColumn> SelectedColumns { get; set; }
}

而且,TableColumn是:

public class TableColumn : ViewModelBase
{
    private string _tableSource;
    public string TableSource
    {
        [DebuggerStepThrough]
        get { return _tableSource; }
        [DebuggerStepThrough]
        set
        {
            if (value != _tableSource)
            {
                _tableSource = value;
                OnPropertyChanged("TableSource");
            }
        }
    }
    private string _colName;
    public string ColName
    {
        [DebuggerStepThrough]
        get { return _colName; }
        [DebuggerStepThrough]
        set
        {
            if (value != _colName)
            {
                _colName = value;
                OnPropertyChanged("ColName");
            }
        }
    }
    private string _customName;
    public string CustomName
    {
        [DebuggerStepThrough]
        get { return _customName; }
        [DebuggerStepThrough]
        set
        {
            if (value != _customName)
            {
                _customName = value;
                OnPropertyChanged("CustomName");
            }
        }
    }

    public override string ToString()
    {
        string sRet;

        if(ColName.Equals("*"))
            sRet = TableSource + "." + ColName;
        else
            sRet = TableSource + "." + ColName + " AS " + CustomName;
        return sRet;
    }
}

最后,ViewModelBase是:

public class ViewModelBase:INotifyPropertyChanged     {         公共事件PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
            PropertyChanged(sender, e);
    }

    protected virtual void OnPropertyChanged(string PropertyName)
    {
        OnPropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
    }
}

问题在于,当我向SelectedQueryView.SelectedColumns添加字段时,即使SelectedColumnsObservableCollection,相关的DataGrid也不会更新。

的Xaml

<DataGrid Grid.Row="0" Grid.Column="2" ItemsSource="{Binding Path=SelectedQueryView.SelectedColumns}" BorderBrush="Black" Margin="5" SelectedItem="{Binding Path=SelectedDestColumn}" AutoGenerateColumns="False" GridLinesVisibility="None" CanUserAddRows="False" RowEditEnding="DataGrid_RowEditEnding" RowHeaderWidth="0" Background="White">
<DataGrid.Columns>
    <DataGridTextColumn Header="Name" Width="*" Binding="{Binding Path=ColName}" IsReadOnly="True"/>
     <DataGridTextColumn Header="Custom Name" Width="*" Binding="{Binding Path=CustomName}" />
 </DataGrid.Columns>
</DataGrid>

有人可以解释一下为什么以及如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

您的课程需要继承 INotifyPropertyChanged 。首先,将TableColumn类更改为此...

   public class TableColumn : INotifyPropertyChanged
    {
        private string _tableSource;
        public string TableSource
        {
            [DebuggerStepThrough]
            get { return _tableSource; }
            [DebuggerStepThrough]
            set
            {
                if (value != _tableSource)
                {
                    _tableSource = value;
                    OnPropertyChanged("TableSource");
                }
            }
        }
        private string _colName;
        public string ColName
        {
            [DebuggerStepThrough]
            get { return _colName; }
            [DebuggerStepThrough]
            set
            {
                if (value != _colName)
                {
                    _colName = value;
                    OnPropertyChanged("ColName");
                }
            }
        }
        private string _customName;
        public string CustomName
        {
            [DebuggerStepThrough]
            get { return _customName; }
            [DebuggerStepThrough]
            set
            {
                if (value != _customName)
                {
                    _customName = value;
                    OnPropertyChanged("CustomName");
                }
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string name)
        {
            var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }

这将使您的类向WPF绑定引擎发出通知,以便在用户表面上应用更改。因此,强烈建议在所有视图模型类上使用通知模式。

此代码在VS2013中编译清理。必须对您的QueryViewItem类应用相同的模式,以便绑定引擎可以找到该类(但不是SelectedColumns成员,因为它已经实现了INPC)。

看起来像这样......

public class QueryViewItem : INotifyPropertyChanged
{
    public ObservableCollection<TableColumn> SelectedColumns { get; set; }
    private string _viewIcon;
    public string ViewIcon
    {
        [DebuggerStepThrough]
        get { return _viewIcon; }
        [DebuggerStepThrough]
        set
        {
            if (value != _viewIcon)
            {
                _viewIcon = value;
                OnPropertyChanged("ViewIcon");
            }
        }
    }
    private string _viewName;
    public string ViewName
    {
        [DebuggerStepThrough]
        get { return _viewName; }
        [DebuggerStepThrough]
        set
        {
            if (value != _viewName)
            {
                _viewName = value;
                OnPropertyChanged("ViewName");
            }
        }
    }
    private string _tableName;
    public string TableName
    {
        [DebuggerStepThrough]
        get { return _tableName; }
        [DebuggerStepThrough]
        set
        {
            if (value != _tableName)
            {
                _tableName = value;
                OnPropertyChanged("TableName");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

答案 1 :(得分:0)

让我看看我是否理解这个问题的关键。根据您的编辑判断,我认为最初,您的问题是您没有实现INotifyPropertyChanged接口,所以要感谢@GayotFow指出这一点。但是,现在您已添加了ViewModelBase课程,现在看来您的问题是,当您在SelectedQueryView.SelectedColumns集合中添加元素时,您的用户界面没有更新。

如果这是正确的,那么我认为您的问题仍然是缺少更新通知。根据您的一条评论,您可以像这样添加元素到您的集合中:

SelectedQueryView.SelectedColumns.Add(column); 

我相信 是你的问题。尽管每个人都在谈论ObservableCollection自动更新用户界面,但我认为如果您在此处添加了对OnPropertyChanged方法的调用,那么您会在UI中看到更新。试试这个:

SelectedQueryView.SelectedColumns.Add(column); 
OnPropertyChanged("SelectedColumns");