C# SelectedValue在代码中设置时不更新
我知道以前有人问过这个问题,但对我来说似乎什么都不管用 我有一个wpf桌面应用程序 我有这个组合框:C# SelectedValue在代码中设置时不更新,c#,wpf,mvvm,C#,Wpf,Mvvm,我知道以前有人问过这个问题,但对我来说似乎什么都不管用 我有一个wpf桌面应用程序 我有这个组合框: <ComboBox ItemsSource="{Binding Users, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Value.Login" SelectedValue="{Binding SelectedManagerUser, Mode=TwoWay,UpdateSou
<ComboBox ItemsSource="{Binding Users, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Value.Login"
SelectedValue="{Binding SelectedManagerUser,
Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="Value"
IsSynchronizedWithCurrentItem="True" />
我知道添加新项目是因为-
谢谢您的SelectedManagerUser属性应更改为此。SelectedManagerUser属性设置为新值,但您不会引发该事件,因此UI不会更新
private UserRecord _selectedManagerUser;
public UserRecord SelectedManagerUser
{
get
{
return _selectedManagerUser;
}
set
{
_selectedManagerUser = value;
RaisePropertyChanged("SelectedManagerUser");
}
}
我不确定你这边出了什么问题,但看看一个可行的解决方案可能会有所帮助 XAML:
代码隐藏:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += WindowLoaded;
var vm = new ViewModel();
vm.Users.Add("u1", new UserRecord { Name = "User 1" });
vm.Users.Add("u2", new UserRecord { Name = "User 2" });
vm.Users.Add("u3", new UserRecord { Name = "User 3" });
DataContext = vm;
}
private void WindowLoaded(object sender, RoutedEventArgs e)
{
// make sure it works after DataContext was set
var vm = (ViewModel)DataContext;
vm.SelectedUser = vm.Users["u2"];
}
}
public class UserRecord
{
public string Name { get; set; }
}
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Dictionary<string, UserRecord> Users { get; }
= new Dictionary<string, UserRecord>();
private UserRecord selectedUser;
public UserRecord SelectedUser
{
get { return selectedUser; }
set
{
selectedUser = value;
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(nameof(SelectedUser)));
}
}
}
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
加载+=窗口加载;
var vm=new ViewModel();
Add(“u1”,新用户记录{Name=“User 1”});
Add(“u2”,新用户记录{Name=“User 2”});
Add(“u3”,新用户记录{Name=“User 3”});
DataContext=vm;
}
已加载私有void窗口(对象发送器,RoutedEventArgs e)
{
//确保它在设置DataContext后工作
var vm=(ViewModel)DataContext;
vm.SelectedUser=vm.Users[“u2”];
}
}
公共类用户记录
{
公共字符串名称{get;set;}
}
公共类视图模型:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
公共字典用户{get;}
=新字典();
私人用户记录选择用户;
公共用户记录选择用户
{
获取{return selectedUser;}
设置
{
selectedUser=值;
PropertyChanged?调用(此,
新属性ChangedEventArgs(名称(SelectedUser));
}
}
}
从Nuget
下载Prism
,并从BindableBase
继承您的类
使用后:
private UserRecord selectedManagerUser;
public UserRecord SelectedManagerUser
{
get { return this.selectedManagerUser; }
set { this.SetProperty(ref this.selectedManagerUser, value); }
}
两种情况中的一种会导致这种情况。首先,可能是因为您没有将
SelectedManagerUser
设置为UserRecord
的一个实例,而该实例不在字典中,或者字典仍然不能用于数据绑定。让我把它们都盖上
使用itemsource
和SelectedItem
绑定时,如果希望SelectedItem
更改反映在UI中,则必须将其设置为可在itemsource
中找到的实例。默认情况下,控件将在源中查找与选定项在引用上相等的项。我99%确信它将使用IEquatable
而不是参考检查您的项目是否实现了它
如果这不是你的问题,那是因为字典不适合数据绑定
字典对于数据绑定来说很糟糕。太糟糕了。如果需要键控集合,并且希望与之绑定,请创建自定义集合。通过一些额外的工作,TItem可以实现INPC(使密钥为只读,tho),集合可以实现INCC。非常适合装订。我为什么要提到这一点?继续读
您的问题是,在组合框中,SelectedItem
实际上是KeyValuePair
类型,而不是UserRecord
。因此绑定将不起作用。如果您获取Snoop的副本并在运行时检查绑定,您将看到这一点
问题是控件不知道jack Shuck关于字典的事。它只知道IEnumerable
Dictionary
实现了IEnumerable
,因此控件为每个键值对创建一个项。SelectedItem也是一个键值对。因此,当您将其绑定到类型为UserRecord
的属性时,是的,它可以使用SelectedValuePath正确设置该值,但它不能(不)[忍者编辑:除非这种行为在过去几年中发生了变化:/]在视图模型中设置值时,迭代可枚举项以找到正确的键值对
如果UserRecord
的键值是该类型中的属性,那么一定要为其创建KeyedCollectionKeyedCollection
实现“IEnumerable”,因此它可以无缝地与绑定一起工作。如果不是,则将其包装在代理中,或添加属性
当我说“用代理包起来”的时候,任何说“什么,像KeyValuePair?”的人我都会在互联网上打你。代理将成为您绑定所依据的值。不要把时间浪费在这篇
SelectedValuePath
废话上。直接与代理合作。当您需要值时,请在最后一刻提取它,而不是在绑定执行后立即提取。什么是temp
?您好,很抱歉,是的,temp是我创建的新键,是从文本框派生的。同样,密钥是有效的。我猜问题是您的新密钥/值不在用户集合中。您必须记住,combobox不会收到关于用户集合中任何新项目的通知,只有在Users
@Pikoh中设置了一个新集合时才会收到通知,就像我在问题中所说的那样,它会被填充,这就是我发布问题的原因。酷,有助于现在问题的全貌。我认为您的IsSynchronizedWithCurrentItem可能会因为绑定到字典而混淆。尝试删除它以查看是否出现新条目。这可能足够了,不过你可能需要采取非字典的方式。金,谢谢。是我的错,我刚刚简写了那处房产的cod。我有你有的。但是谢谢如果你的.NET版本不是太旧,RaisePropertyChanged(nameof(SelectedManagerUser))
也可以工作谢谢必须弹出,但在返回时仍会弹出嗨,我回来了。我现在来看看这个。我会采用你的代码,然后重新开始我的工作。我一定是做错了什么。这对我来说确实有效,但对UserRecord有很多不同的
<ComboBox ItemsSource="{Binding Users}"
DisplayMemberPath="Value.Name"
SelectedValue="{Binding SelectedUser}"
SelectedValuePath="Value" />
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += WindowLoaded;
var vm = new ViewModel();
vm.Users.Add("u1", new UserRecord { Name = "User 1" });
vm.Users.Add("u2", new UserRecord { Name = "User 2" });
vm.Users.Add("u3", new UserRecord { Name = "User 3" });
DataContext = vm;
}
private void WindowLoaded(object sender, RoutedEventArgs e)
{
// make sure it works after DataContext was set
var vm = (ViewModel)DataContext;
vm.SelectedUser = vm.Users["u2"];
}
}
public class UserRecord
{
public string Name { get; set; }
}
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Dictionary<string, UserRecord> Users { get; }
= new Dictionary<string, UserRecord>();
private UserRecord selectedUser;
public UserRecord SelectedUser
{
get { return selectedUser; }
set
{
selectedUser = value;
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(nameof(SelectedUser)));
}
}
}
private UserRecord selectedManagerUser;
public UserRecord SelectedManagerUser
{
get { return this.selectedManagerUser; }
set { this.SetProperty(ref this.selectedManagerUser, value); }
}