c# - 为什么 DependencyProperty.UnsetValue 被传递到 Equals()

标签 c# wpf mvvm combobox

我正在开发一个简单的 WPF 应用程序。目前,该应用程序仅管理 ComboBox 中的视频游戏列表。游戏列表与 XML 文件进行序列化。

当前被破坏的功能是能够从 ComboBox 中选择一个游戏,这使其成为要管理的“事件”游戏。事件游戏将存储为应用程序设置。为此,我使用双向数据绑定(bind)并将 ComboBox 中的 SelectedItem 绑定(bind)到 ViewModel 中的 SelectedGame。

当我运行应用程序并从 ComboBox 中选择一个项目时,我在 Game.Equals(Game other) 方法上得到一个空引用异常。在调试时,我看到 DependencyProperty.UnsetValue 作为参数传递给重写的 Game.Equals(object obj) 方法,这会导致 obj as Game使 obj 为空。

我不明白为什么当我所做的只是从 ComboBox 值中选择一个项目时,为什么首先调用 Equals,所以我猜它是 WPF 原生的东西。在前往 Equals 方法之前,该代码似乎没有遇到任何其他断点,因此我什至不确定如何调试该问题。我也不明白 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>

最佳答案

SelectedItem您的 ComboBox 的更改从 View 中,您会发现您的源属性 (SelectedGame) 可能会被设置两次,一次的值为 null (因为不再选择上一个项目),然后为新选择的项目一次。

如果您的代码依赖于不为 null 的对象,则通常处理的方式是使用简单的 null 值检查:

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

关于c# - 为什么 DependencyProperty.UnsetValue 被传递到 Equals(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32490142/

相关文章:

c# - 搜索多个索引并返回正确的类型

c# - 上传 Blob 时 ASP.NET MVC Controller 导致页面重新加载

wpf - Material 设计 - Wpf - 文本框 - 更改颜色

xaml - 如何使用INavigationAware后退按钮将参数传递到上一页

c# - 如何使用 ReactiveUI 从 CommandParameter 中确定 "canExecute"?

c# - 在用户控件中公开控件的 itemsource 属性

c# - 将对象所有权传递给 WPF 应用程序中的其他线程

c# - MenuItem.IsEnabled 绑定(bind)到是否在列表框中选择了某些内容,但它不会更新

wpf - 绑定(bind) Observable 集合

wpf - 从 ViewModel 闪烁图像