使用MVVM
和ListView
编辑属性时,我收到“堆栈溢出”-Exception 。
我的ViewModel实现了INotifyPropertyChanged
。
我正在制作'日历'。在这个'日历'的每一天,我可以访问两个文件,具体取决于我当前正在查看的那天,这两个文件在我的ViewModel中被转换为两个字符串列表,一个是'Schedule'而另一个是是'笔记'。它们都存储在UI上的ListViews中。
用户可以选择,添加,删除和修改项目。用户可以选择他/她想要的动作,并将其存储在名为SelectedEditingAction
的属性中。
我的SelectedSchedule
的{{1}}和SelectedNote
分别与ViewModel
和Schedule
ListView的所选项目相关联
当用户在ListView上选择一个项目时,相应的SelectedItem属性会发生变化。
Notes
,传递ActivateEditingActions
。如果是附表(布尔):
selected value (int)
从ActivateEditingAction
属性调用false。SelectedNote
从ActivateEditingAction
属性调用true。SelectedNote Property:
SelectedSchedule
ActivateEditingAction
public int SelectedNote
{
get
{
return -1;
}
set
{
if (value != -1)
ActivateEditingAction(false, value);
// I don't set to an underlying field here,
// I always want this to be -1, but I can
// pass in the value to ActivateEditingAction
// that the ListView WANTS me to set to a field
// - Not sure if this is bad code practice
}
}
而且,我正在处理的方法(我之后正在进行EditSelectedItemInListView)
private void ActivateEditingAction(bool isSchedule, int selectedItem)
{
if (SelectedEditingAction == "Nothing")
return;
switch (SelectedEditingAction)
{
case "Add Items": AddItemToListView(isSchedule); break;
case "Remove Items": RemoveSelectedItemFromListView(isSchedule, selectedItem); break;
case "Edit Items": EditSelectedItemInListView(isSchedule, selectedItem); break;
default: throw new NotImplementedException();
}
base.OnPropertyChanged(isSchedule ? "Schedule" : "Notes");
}
删除和添加似乎工作正常。 但是我在编辑时遇到了堆栈溢出。
当我选择了添加编辑操作后,将项目添加到所选列表视图中,完成后再返回 private void AddItemToListView(bool isSchedule)
{
// Getting the new item
string newItem = isSchedule ?
"You have no schedule for this day." :
"You have no notes for this day.";
// Mutation
if (isSchedule) _schedule.Add(newItem);
else _notes.Add(newItem);
}
private void RemoveSelectedItemFromListView(bool isSchedule, int selectedItem)
{
// Confirming the action
var confirm = MessageBox.Show("Are you sure you want to remove this item?", "", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (confirm != MessageBoxResult.Yes)
return;
// Mutation
if (isSchedule) _schedule.RemoveAt(selectedItem);
else _notes.RemoveAt(selectedItem);
// If the ListView doesn't have any more items, we don't want it to be empty!
if ((isSchedule ? _schedule : _notes).Count == 0)
AddItemToListView(isSchedule);
}
,最后我调用{{1} }
然后它进入无限循环,导致堆栈溢出。
所以基本上,我认为发生了什么(出于某种原因)是当我通知属性发生变化时,ListView(这里显示的是Schedule ListView)
ActivatateEditingAction
更新ItemsSource,导致(逻辑上)SelectedIndex重置为0,从而将SelectedIndex属性设置为0,调用base.OnPropertyChanged(isSchedule ? "Schedule" : "Notes");
方法(并继续反复执行),结果为{ {3}}
似乎项目不断添加,然后它会通知属性它已被更改,因此这是一个问题。
我还有一些与删除操作有关的问题。它工作正常 - 直到PropertyChanged出现奇怪的事情。
我可以删除所有这些项目this call stack and a stack over flow exception(即附表列表)
当我从屏幕截图 ee 中找到最后一项时,删除它就可以正常工作,制作出类似的新副本。 删除操作会添加一个新项目“您今天没有时间表”。当集合的计数为0或更低时(我发现<ListView ItemsSource="{Binding Schedule}" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Margin="0,5,0,0" Background="Transparent" BorderThickness="0" Grid.Row="1"
SelectedIndex="{Binding SelectedSchedule}" ItemContainerStyle="{StaticResource ListViewItemContainerStyle}">
<ListBox.ItemTemplate>
<HierarchicalDataTemplate>
<WrapPanel Orientation="Horizontal">
<TextBlock FontSize="15" TextWrapping="Wrap" Text="{Binding}"/>
</WrapPanel>
</HierarchicalDataTemplate>
</ListBox.ItemTemplate>
</ListView>
在这里有效而不是从ActivateEditingAction
调用的时候发现很奇怪)
新的自动生成的项目将添加到相应的列表中,但随后它将停止工作。当我从ListView中删除此项时,然后,像添加项方法一样,它到达base.OnPropertyChanged(),再次调用它,然后当它完成时 - 他再次在PropertyChanged方法中调用它,这发生在结束(这次它不会导致Stack Over Flow,因为如果您确定要执行删除操作,它会在每次询问时暂停)。
我也想请你注意,这些无限循环只发生在我删除了gyazo截图中的所有项目并在Listview中获得一个新项目(“你今天没有时间表。”)之后。当我删除可以在gyazo屏幕截图中看到的最后一项时,不会发生这种情况。 这很奇怪。
为什么在更新值或删除上次自动添加的项目时会进入无限循环?