- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
经过很多小时,我终于找到了导致该错误的问题所在。在显示出现问题的代码之前,我需要解释一下情况。
绑定(bind)和属性结构
在我的应用程序中有一个 ComboBox
绑定(bind)为 ItemSource
Rounds
的列表和 SelectedItem
Round
由用户从列表中选择。
ComboBox
有这样的结构:
<ComboBox ItemsSource="{Binding Rounds}" DisplayMemberPath="RoundName" SelectedItem="{Binding SelectedRound, Mode=TwoWay}" />
如你所见,我已经作为模态 TwoWay
这允许我更新属性 SelectedRound
当用户更改 Item
时自动已选中。
这是类 Round
:
public class Round
{
public int Id { get; set; }
public string Link { get; set; }
public bool Selected { get; set; }
public string RoundName { get; set; }
}
这是 ComboBox
使用的属性:
//List of rounds available
private List<Round> _rounds;
public List<Round> Rounds
{
get { return _rounds; }
set
{
_rounds = value;
OnPropertyChanged();
}
}
//Selected round on ComboBox
private Round _selectedRound;
public Round SelectedRound
{
get { return _selectedRound; }
set
{
_selectedRound = value;
OnPropertyChanged();
}
}
这两个属性都实现了 OnPropertyChanged()
.
属性增值如何运作
在应用程序中有一个名为 LoadRounds()
的方法每次用户按下按钮时调用,此方法有以下指令:
public void LoadRounds(Team team)
{
//Fill the source of ComboBox with the rounds of the new team
Rounds = team.Rounds.ToList(); //<- Create a copy, so no reference
//Get the selected round
SelectedRound = Rounds?.FirstOrDefault(x => x.Id == team.CurrentRound.Id);
}
SelectedRound
取自 team
属性名为 CurrentRound
,特别是每个 team
有一个回合,所以作为一个练习示例:
[Rounds id available in Rounds property]
37487
38406
38405
37488
37486
...
[CurrentRound id of team]
38405
所以SelectedRound
将包含 Round
与 Id
38405 和 linq
查询运行良好。
问题
我设置了一个 breakpoint
在 _selectedRound = value;
, 第一次触发时间 value
是 Round
项目 (38405),但还有第二个触发时间(不应该是)的值为 null
.
我在电脑上花了很多时间来理解为什么会发生这种情况。
似乎 ComboBox
(TwoWay
模式)不知道如何映射 SelectedRound
来自 ItemSource
,所以本质上:
1. [Item Source updated with new Rounds]
2. [SelectedRound updated from the new `Rounds` available]
3. [SelectedRound setter called again with a null value]
我还使用了堆栈调用窗口来查看是否有任何方法再次调用 setter 属性,但是没有调用 setter 的外部方法,所以我猜是 TwoWay
再次触发二传手的模式。
我该如何解决这种情况?我知道这篇文章有点复杂,我可以回答所有问题,并在需要时提供更多详细信息。
谢谢大家,祝你有美好的一天。
更新#1
这是我的 INotifyPropertyChanged
实现:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
}
更新#2
方法LoadRounds
当用户更改 DataGrid
上的选择时调用, DataGrid
包含所有 teams
,所以我得到了 team
由用户在 DataGrid
上选择, 然后调用方法 LoadRounds
.
所有团队都包含在 DataGrid
中, ItemSource
是 List<Team>
.
方法结束LoadRounds
我保存当前Round
的 Team
在名为 SelectedRoundSaved
的特性上,简单地做:
SelectedRoundSaved = Clone(SelectedRound);
通过这种方式我可以防止重新加载 Rounds
如果SelectedRoundSaved
等于SelectedRound
.
Clone
方法允许我克隆对象,并具有以下结构:
public T Clone<T>(T source)
{
if (ReferenceEquals(source, null))
{
return default(T);
}
var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings);
}
它使用 NewtonSoft.Json
图书馆。
这些信息根本不是必需的,但正如我所说,我会添加所有要求您提供的信息,感谢您的关注。
最佳答案
你确定这个顺序是正确的吗?
1. [Item Source updated with new Rounds]
2. [SelectedRound updated from the new `Rounds` available]
3. [SelectedRound setter called again with a null value]
最初绑定(bind)组合框后,我希望顺序是(交换#2 和#3 的顺序)
1. [Item Source updated with new Rounds]
2. [SelectedRound setter called again with a null value]
3. [SelectedRound updated from the new `Rounds` available]
此行为符合我对组合框的预期。当您更新 ItemSource
时,ComboBox 会转储其项目并使用新集合重新加载。因为 ComboBox 是一个选择器,所以它必须检查其 SelectedItem
。如果在新集合中未找到其 SelectedItem
,它会将其 SelectedItem
更新为 null
。所有这一切的发生仅仅是因为 Rounds
setter 中的 OnPropertyChanged();
调用。(注意:您只会在加载和绑定(bind)组合框后看到此行为)
现在有很多方法可以处理这个问题,但在我看来最简单的就是改变操作顺序:
public void LoadRounds(Team team)
{
//Fill the source of ComboBox with the rounds of the new team
var newRounds = team.Rounds.ToList(); //<- Create a copy, so no reference
//Get the selected round
SelectedRound = newRounds.FirstOrDefault(x => x.Id == team.CurrentRound.Id);
Rounds = newRounds;
}
关于c# - Mode=TwoWay 返回 Null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47179883/
我正在开发基于桌面 (Windows 7) 的应用程序,并使用 Qt Creator v 5.6.0 开发程序。我有一个非常奇怪的问题,即 我的程序在 DEBUG 模式下崩溃,但在 RELEASE 模
我爱org-tables ,我用它们来记录各种事情。我现在正在为 Nix 记录一些单行代码(在阅读了 Domen Kožar 的 excellent guide 后,在 this year's Eur
org-mode 是否有一个键绑定(bind)可以在编号/项目符号列表项之间移动,就像您可以对标题一样? 喜欢的功能: org-forward-heading-same-level 大纲下一个可见标题
我知道这有点小,但它一直困扰着我。我正在为一个项目使用 Org-mode,我倾向于经常导出为 PDF 或 HTML,这使我的目录中散落着 PDF、Tex 和 HTML 文件。有没有办法将 Org 模式
有什么方法可以让 org-mode 继续编号列表而不是重新启动? 这是情况。你列了一个类似的列表: Sometimes you can restart the display by doing som
如何在组织模式文件中生成所有标签的枚举列表(例如 :tag:)?假设我有一个以下形式的列表: * Head1 :foo:bar: ** Subhead1 :foo: * Head2
我正在使用 org-mode(Emacs:24.3.1,org-mode: 7.9.3f 8.0.6)作为不同代码片段的数据库语言(目前主要是 elisp 和 python)。这在使用 org-mod
相关问题:org-mode: fontify code blocks natively 截至 2012 年 11 月 1 日,我已经获得了最新的 org-mode 和 emacs 版本(组织存储在 o
有谁知道在使用 ido 模式时区分 dired 模式缓冲区名称与迷你缓冲区中其他类型缓冲区的好方法吗?例如...在 dired 模式缓冲区名称末尾显示正斜杠? 最佳答案 您可以简单地更改dired-m
在这个示例脚本中 import argparse parser = argparse.ArgumentParser() parser.add_argument('--modes', help="tes
我第一次学习“操作系统”。在我的书中,我发现了关于“用户模式”和“内核模式”的这句话: "Switch from user to kernel mode" instruction is execute
我刚刚下载了 Processing 2.0 并尝试从“模式管理器”安装 Android 模式。但是在安装时出现错误提示:“无法将模式“Android 模式”移动到速写本”。我怎样才能摆脱这个错误? 最
在 android L 中,我尝试将相机闪光灯模式设置为 TORCH,它工作正常,但我无法将其更改回闪光灯模式 AUTO 或闪光灯模式 打开。我只能返回闪存模式 OFF。我尝试了像 camera360
有 2 台机器,A 和 B。有 2 个分支,p16 和 c2。 A 有一个 ext3 文件系统,但在 B 上,存档位于带有 vfat 的 truecrypt 驱动器上,mount 显示 rw,uid=
我有 linum-mode在我的 Emacs 配置中全局启用。全局启用意味着它也适用于不受欢迎的速度条。 我为这个问题找到的唯一建议是在存档的 Emacs 帮助邮件列表中,它建议以下 speedbar
Google Cloud Firestore 将很快取代旧的 Google Cloud Datastore。然后可以选择在“ native 模式”或“数据存储模式”下使用 Cloud Firestor
org-mode的版本我的版本 Emacs 附带的(24.5.2) 是 8.2.10 .我已安装版本 8.3.1从 ELPA 并将其添加到我的 init 文件中: (add-to-list 'load
The org-mode manual指出 org-mode 将“”“...在 shell 链接”“”中执行命令,但它不显示此类链接的语法。 我希望能有一个简单完整的示例来说明这种 shell 链接是
我正在尝试在 emacs 24 中使用 dart 模式和 d 模式。如果我单独使用任何一种模式,一切都很好。如果我分别对每种类型的文件使用这两种模式,我在尝试缩进 D 代码时会出错。 以下是在初始化时
我的应用程序中有 CupertinoDatePicker 以使用以下代码选择日期和时间: formatColumn( widget: Consumer( builder: (_, mcProvide
我是一名优秀的程序员,十分优秀!