0

我有奇怪的 WPF ObservableCollection 行为。由于不明确的原因,当集合被修改并且我的类的某些属性中的 getter-method 中存在另一个条件时,它不会修改 View。虽然调用了 CollectionChanged 事件!在 getter 方法集合中没有条件的情况下效果很好。

太复杂和啰嗦了,无法在这里解释我在我的工作项目中所做的事情。因此,我做了小简化项目并模拟相同的行为。这个项目比千字更好地向您展示问题。

要查看问题 - 按原样启动项目,看看它是如何工作的。这真的很简单,2 个单选按钮,datagrid,仅此而已。然后转到 MainWindowViewModel,GridItems-property,取消注释代码并再次启动项目。看到不同。修改集合时,不会调用 GridItems-property 的 get 方法(我用调试器检查它)。未调用的方法如何影响某些东西???我对此没有任何想法。帮助请。

项目链接: http ://www.megafileupload.com/en/file/443850/ObservableCollection-zip.html

class MainWindowViewModel : ViewModelBase
    {
        private ObservableCollection<GridItem>  _totalStorage;

        private ObservableCollection<GridItem> _gridItems;
        public ObservableCollection<GridItem> GridItems
        {
            get
            {
                //if (_gridItems.Count == 0)
                //{
                //    return _totalStorage;
                //}
                return _gridItems;
            }
            set
            {
                _gridItems = value;
                RaisePropertyChanged("GridItems");
            }
        }

        public MainWindowViewModel()
        {
            _totalStorage = new ObservableCollection<GridItem>();
            _gridItems = new ObservableCollection<GridItem>();

            GridItemsInit();
            _gridItems.CollectionChanged += CollectionChanged;
        }

        /// <summary>
        /// Collection change event handler
        /// </summary>
        /// <param name="o"></param>
        /// <param name="e"></param>
        private void CollectionChanged(object o, NotifyCollectionChangedEventArgs e)
        {

        }


        private void GridItemsInit()
        {
            _totalStorage.Add(new GridItem
            {
                Name = "Igor",
                LastName = "Balachtin",
                FilerField = FileStatusEnum.All
            });

            _totalStorage.Add(new GridItem
            {
                Name = "Misha",
                LastName = "Ivanov",
                FilerField = FileStatusEnum.All
            });

            _totalStorage.Add(new GridItem
            {
                Name = "Ahmed",
                LastName = "Magamed",
                FilerField = FileStatusEnum.All
            });

            _totalStorage.Add(new GridItem
            {
                Name = "abrek",
                LastName = "cheburek",
                FilerField = FileStatusEnum.All
            });

            _totalStorage.Add(new GridItem
            {
                Name = "Irka",
                LastName = "Dirka",
                FilerField = FileStatusEnum.All
            });
        }

        private void RefreshGridSource(string statusParam)
        {
            _gridItems.Clear();

            //Если нажали на баттон new
            if (statusParam.Equals(FileStatusEnum.All.ToString()))
            {
                foreach (var item in _totalStorage)
                {
                    _gridItems.Add(item);
                }
            }

            //Если нажали на archived
            else if (statusParam.Equals(FileStatusEnum.Filtered.ToString()))
            {
                foreach (var item in _totalStorage.Where(g => g.FilerField == FileStatusEnum.Filtered))
                {
                    _gridItems.Add(item);
                }    
            }
        }


        private RelayCommand<object> _radioCommand;

        public RelayCommand<object> RadioCommand
        {
            get { return _radioCommand ?? (_radioCommand = new RelayCommand<object>(HandlerFileRadio)); }
        }

        private void HandlerFileRadio(object obj)
        {
            if (obj == null)
                return;

            var statusParam = obj.ToString();

            RefreshGridSource(statusParam);
        }

    }


Look at this sample.
//if (_gridItems.Count == 0)
//{
//    return _totalStorage;
//}

Model:

 public enum FileStatusEnum
    {
        All = 0,
        Filtered
    }

    public class GridItem
    {
        public String Name { get; set; }
        public String LastName { get; set; }

        public FileStatusEnum FilerField
        {
            get; set;
        }
    }

xml:

<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="3*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Column="0">
            <RadioButton Margin="5" IsChecked="True" Command="{Binding RadioCommand}"
                                     CommandParameter="All">All</RadioButton>
            <RadioButton Margin="5" Command="{Binding RadioCommand}"
                                     CommandParameter="Filtered">Filtered</RadioButton>
        </StackPanel>
        <DataGrid Grid.Column="1" ItemsSource="{Binding GridItems}" CanUserAddRows="False" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" IsReadOnly="True" />
                <DataGridTextColumn Header="LastName" Binding="{Binding LastName}" IsReadOnly="True" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>

真的更好地在这里发布所有代码而不是链接?:/

4

2 回答 2

0

一旦您更改记录,您的财产就不会通知。所以请在更改集合后通知。

在集合更改后在 RefreshGridSource 方法中添加以下行。

RaisePropertyChanged("GridItems");

于 2013-08-23T10:46:55.437 回答
0

您的GridItems财产可以退回_totalStorage_gridItems根据条件退回;_totalStorage并且_gridSettings是 的两个不同实例ObservableCollection。最初,当_gridItems没有项目时,您的GridItems属性将返回_totalStorage到 WPF,并且 WPF 在此实例上侦听任何 CollectionChanged 事件。

在您的RefreshGridSource方法中,您正在更新_gridItems(与 不同的实例_totalStorage),WPF 对此一无所知。

GridItems但是,当您从方法中更改属性的属性时, RefreshGridSourceWPF 将重新读取该属性GridItems- 这一次,WPF 获取_gridItems集合并按您预期的方式工作。

希望,我已经解释得很好了。

于 2013-08-23T11:38:49.347 回答