Excepción de referencia nula en PresentationFramework

A continuación se muestra un ejemplo mínimo, posiblemente no podría reducirlo más que esto.

Creo un CollectionView filtrado en vivo en el ViewModel como este:

using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Windows.Data; using System.Windows; namespace AntiBonto.ViewModel { [Serializable] public class Person { public event PropertyChangedEventHandler PropertyChanged; protected void RaisePropertyChanged([CallerMemberName] String propertyName = "") { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } public string Name { get; set; } public override string ToString() { return Name; } private int num; public int Num { get { return num; } set { num = value; RaisePropertyChanged(); } } } class ObservableCollection2 : ObservableCollection { public ObservableCollection2() : base() { } public ObservableCollection2(T[] t) : base(t) { } public void AddRange(IEnumerable collection) { foreach (var i in collection) { Items.Add(i); } OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } } class MainWindow: ViewModelBase { public MainWindow() { } private ObservableCollection2 people = new ObservableCollection2(); public ObservableCollection2 People { get { return people; } set { people = value; RaisePropertyChanged(); } } public ICollectionView Team { get { CollectionViewSource cvs = new CollectionViewSource { Source = People, IsLiveFilteringRequested = true, LiveFilteringProperties = { "Num" } }; cvs.View.Filter = p => ((Person)p).Num != 11; return cvs.View; } } public ICollectionView Ujoncok { get { CollectionViewSource cvs = new CollectionViewSource { Source = People, IsLiveFilteringRequested = true, LiveFilteringProperties = { "Num" } }; cvs.View.Filter = p => ((Person)p).Num == 11; return cvs.View; } } } } 

La GUI tiene un botón que modifica un objeto Person en la colección People:

            

Cargo los datos de un archivo XML como este:

 using System; using System.IO; using System.Linq; using System.Windows; using System.Xml.Serialization; namespace AntiBonto { [Serializable] public class AppData { public Person[] Persons; } public partial class MainWindow : System.Windows.Window { public MainWindow() { InitializeComponent(); Loaded += MainWindow_Loaded; } private string filepath = "state.xml"; private AppData AppData { get { return new AppData { Persons = viewModel.People.ToArray()}; } set { viewModel.People.AddRange(value.Persons);} } private void MainWindow_Loaded(object sender, RoutedEventArgs e) { var xs = new XmlSerializer(typeof(AppData)); if (File.Exists(filepath)) { using (var file = new StreamReader(filepath)) { AppData = (AppData)xs.Deserialize(file); } } } private ViewModel.MainWindow viewModel { get { return (ViewModel.MainWindow)DataContext; } } private void Button_Click(object sender, RoutedEventArgs e) { Person p = viewModel.People.First(q => q.Name == "Ferencz Katalin"); if (p.Num == 11) p.Num = 0; else p.Num= 11; } } } 

y el archivo XML es este:

     Person1 0   Person2 0    

Cuando hago clic en el botón una o dos veces, obtengo una excepción de NullReference . No hay excepción interna. La excepción no surge en mi código, sino en el código de marco, por lo que no muestra el origen, no puedo averiguar qué objeto es nulo y de dónde proviene la excepción. No logré configurar “entrar en las fonts .NET”, todavía me dice que no hay una fuente disponible.

Aquí hay un rastro de stack:

at System.Windows.Data.ListCollectionView.RestoreLiveShaping () at System.Windows.Threading.ExceptionWrapper.InternalRealCall (Delegate callback, Object args, Int32 numArgs) ExplicaciónWatchows.Threading. args, Int32 numArgs, Delegate catchHandler) en System.Windows.Threading.DispatcherOperation.InvokeImpl () en System.Windows.Threading.Dispatchplacaspañol.IncokeInSecurityContext (Estado del objeto) en System.Threading.ExecutionConte. estado, Boolean preserveSyncCtx) en System.Threading.ExecutionContext.Run (Ejecución de ExecutionContextContext, Devolución de llamada de ContextCallback, Estado del objeto, Boolean preserveSyncCraunidad), Estado de cuenta, Pieza de protección de la naturaleza, Contexto, Pieza de laca, Pieza de laca, Recorrido de la mesa de trabajo, Estado de cuenta, Pieza de protección, Pieza de protección, Pieza de protección, Pieza de protección, Pincel .Run (CulturePreservingExecutionContextecutionContext, Callback de ContextCallback, O bject state) en System.Windows.Threading.DispatcherOperation.Invoke () en System.Windows.Threading.Dispatcher.ProcessQueue () en System.Windows.Threading.Dispatcher.WndProcHook (IntPtr hwnd, Intcppppppppppppppppppppppppppppppppppppppppppppppppppp> Boolean y manipulado) en MS.Win32.HwndWrapper.WndProc (IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean & manejado) en MS.Win32.pañe en las partes de las partes de la red de personas y servicios. Devolución de llamada delegada, Argumentos de objeto, Números de Int32) en System.Windows.Threading.ExceptionWrapper.TryCatchWhen (Origen de objeto, Devolución de llamada de delegado, Argumentación de objeto, Int32 numArgs, Delegate catchHandler) en System.Windows.Threading.Dispatcher.LegacyInvokeImpl (Dispatch) timeout, Delegate method, Object args, Int32 numArgs) en MS.Win32.HwndSubclass.SubclassWndProc (IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr o Estado de la actividad de la empresa). .Dispa tcher.PushFrameImpl (marco DispatcherFrame) en System.Windows.Threading.Dispatcher.PushFrame (marco DispatcherFrame) en System.Windows.Application.RunDispatcher (Ignorar objeto) en System.Windows.Application.RunInternal (ventana de ventana) en SystemWind. Application.Run (ventana de ventana) en System.Windows.Application.Run () en AntiBonto.App.Main () en D: \ Marci \ Programozás \ AntiBonto \ AntiBonto \ obj \ Debug \ App.g.cs: línea 0 en System.AppDomain._nExecuteAssembly (RuntimeAssembly assembly, String [] args) en System.AppDomain.ExecuteAssembly (String assemblyFile, Evidence assemblySecurity, String []UssV.An.S.) .ThreadStart_Context (estado del objeto) en System.Threading.ExecutionContext.RunInternal (ejecución de ExecutionContextContext, callback ContextCallback, estado del objeto, Boolean preserveSyncCttcxt.inclucencia) eserveSyncCtx) en System.Threading.ExecutionContext.Run (Ejecución de ExecutionContext, callback ContextCallback, estado del objeto) en System.Threading.ThreadHelper.ThreadStart ()

No tengo idea de por qué, pero esto solucionó el error:

 public ICollectionView Team { get { CollectionViewSource cvs = new CollectionViewSource { Source = People, IsLiveFilteringRequested = true, LiveFilteringProperties = { "Num" } }; cvs.View.Filter = p => ((Person)p).Num != 11; cvs.View.CollectionChanged += EmptyEventHandler; return cvs.View; } } private void EmptyEventHandler(object sender, NotifyCollectionChangedEventArgs e) { } 

Estaba tratando de depurar dónde ocurre la excepción y quería establecer un punto de interrupción cuando cambia la colección. La suscripción al evento hizo que la excepción desapareciera.

Pasé mucho tiempo tratando de depurar System.Windows y no llegué a ninguna parte, puedes intentarlo.

En términos de una solución alternativa de curita que al menos funcionará, de mi pregunta encontré que el new CollectionViewSource causa el problema, mientras que CollectionViewSource.GetDefaultView no lo hace.

Usted menciona que hay dos problemas con esto:

1) Estoy modificando la colección base todo el tiempo y necesito que mis filtros se actualicen

Puede solucionar esto utilizando ObservableCollections y escuchando ediciones, y luego actualice sus instancias filtradas.

Por lo tanto, cada vez que necesite un CollectionViewSource, cree un nuevo ObservableCollection y manténgalo al tanto, agregue un oyente a la ObservableCollection original y envíe actualizaciones a la versión de CollectionViewSource.

¿Elegante? No funcional? Sí.

2) Estoy usando Live Shaping que no está disponible con GetDefaultView.

Siempre ha estado disponible para mí usando GetDefaultView, ¿puede mostrar dónde está creando la vista?

Una similitud que he notado es que estoy usando una extensión de ObservableCollection. ¿Tiene el problema si solo usa una colección observable estándar?