2013-08-23 73 views
0

我有奇怪的WPF ObservableCollection行爲。由於收集修改時不清楚的原因,並且在我的類的某些屬性中getter-method中存在另一個條件,因此它不會修改View。雖然CollectionChanged事件被調用! 沒有條件的getter方法收集工作良好。ObservableCollection不要修改視圖

太複雜和冗長的解釋,這裏我做我的工作項目。因此,我做了小型簡化項目並模擬相同的行爲。這個項目顯示你的問題勝過千言萬語。

要看到問題 - 啓動項目,看看它是如何工作的。它非常簡單,2個單選按鈕,datagrid,沒有別的。然後轉到MainWindowViewModel,GridItems屬性,取消註釋註釋代碼並再次啓動項目。看到不同。當收集修改時,GridItems屬性的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> 

真是再好不過了張貼在這裏,而不是鏈接的所有代碼? :/

+1

你可以在這裏發佈ViewModel代碼嗎? – sthotakura

+1

@monstr,大多數沒有資源下載一個zip文件,並通過一系列規定的步驟運行。這意味着你的問題屬於「太寬泛」範疇,我會爲你舉報。請編輯您的問題,重點關注視圖模型中行爲不當的特定片段。格式化的源代碼將幫助您快速解決問題。 –

+0

你可能應該只有總集合並綁定到一個['CollectionView'](http://msdn.microsoft.com/en-us/library/system.windows.data.collectionview.aspx)過濾器。 –

回答

0

一旦你改變記錄後,你的財產不是Notifying.so請更改集合後通知。

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

RaisePropertyChanged(「GridItems」);

+0

ObservableCollection會自動通知是否更改。反正也不行... – monstr

+0

也在GridItemsInit方法中添加過濾記錄。其工作正常.. –

+0

因此,如果我沒有過濾記錄它不能正常工作。 Thx,但它沒有解決問題) – monstr

0

你的GridItems屬性可以返回_totalStorage_gridItems取決於條件; _totalStorage_gridSettings是兩個不同的ObservableCollection的實例。最初,當_gridItems沒有項目時,您的GridItems屬性將_totalStorage返回給WPF,並且WPF在此實例上偵聽任何CollectionChanged事件。

在您的RefreshGridSource方法中,您正在更新_gridItems(與_totalStorage不同的實例),WPF不知道該方法。

但是,當你RASIE財產變GridItems財產RefreshGridSource方法WPF將重新讀取屬性GridItems - 這一次,WPF得到_gridItems收集和它的作品如你預期。

希望,我已經解釋得很清楚了。

+0

我填滿了這麼愚蠢......讓我們一步一步地說。爲什麼當我打電話 ** _ gridItems.Clear(); ** _gridItems不告訴WPF更新網格內容?因爲** _ gridItems **是ObservableCollection,並且必須通知WPF關於它的任何更改。 – monstr

+0

正如我在我的回答中所提到的,WPF並不知道你的'_gridItems',但是當WPF讀取'GridItems'屬性時'_totalStorage'。試試'GridItems.Clear()'它會清除網格,因爲當'_gridItems.Count = 0'時'GridItems'將指向'_totalStorage'。 – sthotakura

+0

我明白了。 WPF存儲了第一個呼籲的ObservableCollection。並與它分離GridItems。我很驚訝。偉大的thx! – monstr