2015-09-09 28 views
1

我正在開發一個簡單的WPF應用程序。目前,該應用程序僅管理ComboBox中的視頻遊戲列表。遊戲列表將序列化到XML文件或從XML文件中進行序列化。爲什麼DependencyProperty.UnsetValue被傳入Equals()

當前破壞的功能是從ComboBox中選擇一個遊戲,使其成爲「活動」遊戲進行管理的功能。活動遊戲將作爲應用程序設置存儲。爲了達到這個目的,我使用雙向數據綁定並將ComboBox中的SelectedItem綁定到ViewModel中的SelectedGame。

當我運行應用程序並從ComboBox中選擇一個項目時,我在Game.Equals(Game other)方法上得到一個空引用異常。在調試時,我看到DependencyProperty.UnsetValue被作爲參數傳遞給被覆蓋的Game.Equals(object obj)方法,該方法導致obj as Game使obj爲空。

我不明白爲什麼當Equals被首先調用時,我正在從ComboBox值中選擇一個項目,所以我猜這是WPF原生的東西。該代碼似乎沒有擊中任何其他斷點前,等於方法,所以我甚至不知道如何調試問題。我也不明白DependencyProperty.UnsetValue來自哪裏。我只是完全迷失在這裏,並希望得到任何見解,包括如何進一步調試。

編輯:正如Glen所提到的,Equals必須由WPF的某個基礎組件調用。至少現在,我的解決方案是簡單地在我的Equals覆蓋中添加一個空檢查。

模型類

public class Game : IEntity, IEquatable<Game> 
{ 
    [XmlElement("Name")] 
    public string Name { get; set; } 

    [XmlElement("ExecutablePath")] 
    public string ExecutablePath { get; set; } 

    public Game(string name, string executablePath) 
    { 
     Name = name; 
     ExecutablePath = executablePath; 
    } 

    private Game() { } // Required for XML serialization. 

    public bool Equals(Game other) 
    { 
     return Name.EqualsIgnoreCase(other.Name); 
    } 

    public override bool Equals(object obj) 
    { 
     return Equals(obj as Game); 
    } 
} 

視圖模型

public class GamesViewModel 
{ 
    // The GameRepository retrieves the game collection from the XML file. 
    private readonly GameRepository _gameRepository; 

    public ObservableCollection<Game> Games 
    { 
     get { return new ObservableCollection<Game>(_gameRepository.Items); } 
    } 

    public Game SelectedGame 
    { 
     get { return Settings.Default.ActiveGame; } 
     set 
     { 
      if (!Settings.Default.ActiveGame.Equals(value)) 
      { 
       Settings.Default.ActiveGame = value; 
       Settings.Default.Save(); 
      } 
     } 
    } 

    public GamesViewModel() 
    { 
     _gameRepository = RepositorySingletons.GameRepository; 
    } 
} 

查看

<UserControl x:Class="ENBOrganizer.UI.Views.GamesView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:ENBOrganizer.UI.ViewModels" 
      mc:Ignorable="d" > 
    <UserControl.DataContext> 
     <local:GamesViewModel /> 
    </UserControl.DataContext> 
    <Grid> 
     <ComboBox Name="GamesComboBox" ItemsSource="{Binding Games}" SelectedItem="{Binding SelectedGame}"> 
      <ComboBox.ItemTemplate> 
       <DataTemplate> 
         <TextBlock Text="{Binding Name}" VerticalAlignment="Center" Padding="5,0,0,0" /> 
       </DataTemplate> 
      </ComboBox.ItemTemplate> 
     </ComboBox> 
    </Grid> 
</UserControl> 
+0

你的Equals方法是非常懶惰。你應該能夠處理這個,而不會拋出NRE。 – Will

+0

我很滿意一個空檢查。我只想了解爲什麼null首先被傳入。 – SeeSharpCode

回答

1

SelectedItem從您的ComboBox視圖中更改,您會發現您的源媒體資源(SelectedGame)可能會設置兩次,一次使用值null(因爲不再選擇上一個項目),然後一次用於新選擇的項目。

如果您有依賴於不被空的對象代碼,這通常處理的方法是使用一個簡單的空值檢查:

if (value != null) 
{ 
    // Code that relies on value not being null 
} 
+0

在這一點上,我真的沒有專門依賴空檢查的代碼。我將來可能需要這樣做,但對於早期的開發目的,我只有2個遊戲在ComboBox中,所以我的選擇永遠不會爲空。 可能你知道爲什麼Equals方法被調用時,我所做的只是在ComboBox中選擇一個項目? – SeeSharpCode

+0

您的SelectedGame屬性的setter具有ActiveGame.Equals(value)....... –

+0

這是我第一次猜測。我在SelectedGame屬性的setter上設置了一個斷點,但Equals方法在setter被擊中之前拋出異常。 – SeeSharpCode

相關問題