NullReferenceException Использование Treeview и PropertyChanged - PullRequest
2 голосов
/ 25 февраля 2012

Я получаю исключение NullReferenceException при обновлении связанного свойства в моей модели представления.Это происходит только тогда, когда я использую элемент управления treeview в представлении.Если я заменил его списком, исключение исчезнет.

Это то место, где отладчик ломается в моем коде:

PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

Примерно через 30 вызовов, во многих сборках PresentationFramework и WindowsBaseна самом деле возникает исключение:

PresentationFramework.dll!System.Windows.StyleHelper.EvaluateOldNewStates()

Это древовидное представление:

<TreeView DockPanel.Dock="Bottom" ItemsSource="{Binding Source={StaticResource cvs}, Path=Groups}"
                  ItemTemplate="{StaticResource categoryTemplate}" SelectedItemChanged="TreeView_SelectedItemChanged"/>

И если вместо этого использовать этот список, проблема исчезнет:

<ListBox DockPanel.Dock="Bottom" ItemsSource="{Binding ApplicationServers}" DisplayMemberPath="Name"
                     SelectedItem="{Binding SelectedApplicationServer}" Height="auto"/>

Я не уверен, что это поможет, но вот свойство, которое обновляется:

public ObservableCollection<ApplicationServer> ApplicationServers
        {
            get { return this._applicationServers; }

            private set
            {
                this._applicationServers = value;
                this.NotifyPropertyChanged(() => this.ApplicationServers);
            }
        }

А вот вызов для обновления этого свойства:

this.ApplicationServers = new ObservableCollection<ApplicationServer>(ApplicationServerLogic.GetAll().ToList());

Имееткто-нибудь испытывал что-нибудь подобное?Я не знаю, что является причиной проблемы, и я испытываю желание просто использовать список.На самом деле, мне в данный момент приходится пользоваться списком.Как я могу даже устранить эту проблему?Может быть, это ошибка в сборке PresentationFramework?

Кроме того, это мой код, показывающий обработку события измененного элемента.

private void TreeView_SelectedItemChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs<object> e)
        {
            ((ApplicationServerViewModel)DataContext).SelectedApplicationServer = e.NewValue as ApplicationServer;
        }

РЕДАКТИРОВАТЬ: Кто-топопросили больше кода, вот оно:

        <CollectionViewSource x:Key="cvs" Source="{Binding ApplicationServers}">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="DeploymentEnvironment"/>
            </CollectionViewSource.GroupDescriptions>
            <CollectionViewSource.SortDescriptions>
                <scm:SortDescription PropertyName="Name" Direction="Ascending"/>
            </CollectionViewSource.SortDescriptions>
        </CollectionViewSource>

        <!-- Our leaf nodes (server names) -->
        <DataTemplate x:Key="serverTemplate">
            <TextBlock Text="{Binding Path=Name}"/>
        </DataTemplate>

        <!-- Note: The Items path refers to the items in the CollectionViewSource group (our servers).
                   The Name path refers to the group name. -->
        <HierarchicalDataTemplate x:Key="categoryTemplate"
                                  ItemsSource="{Binding Path=Items}"
                                  ItemTemplate="{StaticResource serverTemplate}">
            <TextBlock Text="{Binding Path=Name}" FontWeight="Bold"/>
        </HierarchicalDataTemplate>

1 Ответ

1 голос
/ 26 февраля 2012

Хотя это не отвечает на вопрос почему в вашем случае; Одним из подходов будет добавление элементов в экземпляр коллекции вместо изменения экземпляра с помощью установщика. Удалите выставленный сеттер и просто добавьте элементы по мере необходимости, что вызовет событие CollectionChanged в базовой коллекции, которое предоставит вам то, что вы в конечном итоге получите.

        public ObservableCollection<ApplicationServer> ApplicationServers
        {
            get { return this._applicationServers; }
        }

        ApplicationServers.Add(...);
...