我有奇怪的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>
真的更好地在这里发布所有代码而不是链接? :/
答案 0 :(得分:0)
在您的财产未通知后更改记录。请在更改集合后通知。
在集合更改后,在RefreshGridSource方法中添加以下行。
RaisePropertyChanged( “GridItems”);
答案 1 :(得分:0)
根据条件,您的GridItems
媒体资源可以返回_totalStorage
或_gridItems
; _totalStorage
和_gridSettings
是ObservableCollection
的两个不同的实例。最初,当_gridItems
没有项目时,您的GridItems
属性会将_totalStorage
返回给WPF,并且WPF会在此实例上侦听任何CollectionChanged事件。
在RefreshGridSource
方法中,您正在更新_gridItems
(来自_totalStorage
的不同实例),WPF不知道该内容。
但是,当您从GridItems
方法更改了RefreshGridSource
属性的rasie属性时,WPF将重新读取属性GridItems
- 这次,WPF获得_gridItems
个收集并且它按预期工作。
希望,我已经解释得很好。