ObservableCollection不修改视图

时间:2013-08-23 10:03:56

标签: wpf observablecollection

我有奇怪的WPF ObservableCollection行为。通过不清楚的原因何时修改了集合并且在我的类的某些属性中getter-method中存在另一个条件,它不会修改View。虽然调用了CollectionChanged事件! 没有条件的getter方法集合效果很好。

过于复杂和冗长,在这里解释我在工作项目中做了什么。因此,我进行小型简化项目并模拟相同的行为。这个项目向你展示的问题比千言万语更好。

要查看问题 - 按原样启动项目,看看它是如何工作的。它非常简单,2个radiobuttons,datagrid,没有别的。然后转到MainWindowViewModel,GridItems-property,取消注释注释代码并再次启动项目。看到不同。当集合修改时,GridItems-property的get-method不能调用(我用调试器检查它)。如何不调用方法可以对某些事情产生影响?我对它一无所知。帮助PLZ。

项目链接: 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;
        }
    }

的Xaml:

<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>

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

2 个答案:

答案 0 :(得分:0)

在您的财产未通知后更改记录。请在更改集合后通知。

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

RaisePropertyChanged( “GridItems”);

答案 1 :(得分:0)

根据条件,您的GridItems媒体资源可以返回_totalStorage_gridItems; _totalStorage_gridSettingsObservableCollection的两个不同的实例。最初,当_gridItems没有项目时,您的GridItems属性会将_totalStorage返回给WPF,并且WPF会在此实例上侦听任何CollectionChanged事件。

RefreshGridSource方法中,您正在更新_gridItems(来自_totalStorage的不同实例),WPF不知道该内容。

但是,当您从GridItems方法更改了RefreshGridSource属性的rasie属性时,WPF将重新读取属性GridItems - 这次,WPF获得_gridItems个收集并且它按预期工作。

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