在代码中设置时,SelectedValue不会更新

时间:2016-12-20 11:51:39

标签: c# wpf mvvm

我之前可以看到这个问题,但似乎没有什么对我有用。

我有一个wpf桌面应用程序。

我有这个组合框:

<ComboBox ItemsSource="{Binding Users, Mode=TwoWay,  UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Value.Login"
   SelectedValue="{Binding SelectedManagerUser, 
   Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  
   SelectedValuePath="Value"  
   IsSynchronizedWithCurrentItem="True"  />

数据源是字典对象:

public Dictionary<string,UserRecord> Users
{
    get
    {
       //get data
    }
    set { _Users =  value; RaisePropertyChanged(Constants.VM_Users); }
}

我在MVVM中添加了一个新条目并更新了数据。

然后我在mvvm中设置了所选项目:

private UserRecord _selectedManagerUser;
public UserRecord SelectedManagerUser 
{ 
    get
    {
        return _selectedManagerUser;
    }
    set
    {
        _selectedManagerUser = value;
        RaisePropertyChanged("SelectedManagerUser");
    }
}
SelectedManagerUser = Users[temp];

public class UserRecord : ViewModelBase
{
    private int _Active;
    private int _UserRecordId;
    private string _UserRef;
    private string _FName;
    private string _SName;
    private string _Login;
    private string _Salt;
    private int _IsAdmin;
    private string _FullName;
    private string _Branch;
    private string _Position;
    private string _Department;

    public int Disabled { get { return _Active; } set { _Active = value; RaisePropertyChanged(InformedWorkerCommon.Constants.VM_Active); } }
    public int UserRecordId { get { return _UserRecordId; } set { _UserRecordId = value; RaisePropertyChanged("UserRecordId"); } }
    public string UserRef { get { return _UserRef; } set { _UserRef = value; RaisePropertyChanged(InformedWorkerCommon.Constants.VM_UserRef); } }
    public string FName { get { return _FName; } set { _FName = value; RaisePropertyChanged(InformedWorkerCommon.Constants.VM_FName); } }
    public string SName { get { return _SName; } set { _SName = value; RaisePropertyChanged(InformedWorkerCommon.Constants.VM_SName); } }
    public string Login { get { return _Login; } set { _Login = value; RaisePropertyChanged(InformedWorkerCommon.Constants.VM_Login); } }
    public string Salt { get { return _Salt; } set { _Salt = value; RaisePropertyChanged(InformedWorkerCommon.Constants.VM_Salt); } }
    public int IsAdmin { get { return _IsAdmin; } set { _IsAdmin = value; RaisePropertyChanged(InformedWorkerCommon.Constants.VM_IsAdmin); } }
    public string Branch { get { return _Branch; } set { _Branch = value; RaisePropertyChanged(InformedWorkerCommon.Constants.VM_Branch); } }
    public string Position { get { return _Position; } set { _Position = value; RaisePropertyChanged(InformedWorkerCommon.Constants.VM_Position); } }
    public string Department { get { return _Department; } set { _Department = value; RaisePropertyChanged(InformedWorkerCommon.Constants.VM_Department); } }
    public string FullName { get { return FName + ", " + SName; } set { _FullName = value; RaisePropertyChanged(InformedWorkerCommon.Constants.VM_Fullname); } }
}

我知道新项目已添加,因为 -

  1. 我可以在下拉列表中看到它
  2. 我在代码中设置断点并进行检查。
  3. 组合框只显示一个空值。

    我还能尝试其他什么吗?

    感谢

4 个答案:

答案 0 :(得分:0)

您的SelectedManagerUser属性应更改为此属性。 SelectedManagerUser属性设置为新值,但您不会引发该事件,因此不会更新UI。

    private UserRecord _selectedManagerUser;
    public UserRecord SelectedManagerUser 
    { 
        get
        {
            return _selectedManagerUser;
        }
        set
        {
            _selectedManagerUser = value;
            RaisePropertyChanged("SelectedManagerUser");
        }
    }

答案 1 :(得分:0)

不确定您身边出了什么问题,但查看有效的解决方案可能会有所帮助。

XAML:

<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)));
        }
    }
}

答案 2 :(得分:0)

Prism下载Nuget并从BindableBase继承您的课程。

使用后:

private UserRecord selectedManagerUser;

public UserRecord SelectedManagerUser
{
    get { return this.selectedManagerUser; }
    set { this.SetProperty(ref this.selectedManagerUser, value); }
}

答案 3 :(得分:0)

两件事之一可能导致这种情况。首先,可能是因为您没有将SelectedManagerUser设置为UserRecord的不在字典中的实例,或者字典仍然很难进行数据绑定。 Lemme盖住他们两个。

当您使用ItemsSourceSelectedItem绑定时,如果您希望在UI中反映SelectedItem更改,则必须将其设置为可在{{ItemsSource内找到的实例1}}。默认情况下,控件将在源中查找与所选项目相同的项目。我99%肯定会使用IEquatable<T>而不是参考检查您的项目是否实现了它。

如果那不是你的问题,那就是因为字典很难进行数据绑定。

字典对于数据绑定是可怕的。太可怕了。如果您需要键控集合并且想要绑定它,请创建一个扩展KeyedCollection的自定义集合。通过一些额外的工作,TItem可以实现INPC(使密钥只读,tho),集合可以实现INCC。适用于绑定。为什么我提这个?请继续阅读...

您的问题是,在ComboBox中,SelectedItem实际上是KeyValuePair<string,UserRecord>类型,而不是UserRecord。所以绑定不起作用。如果你抓住Snoop的副本并在运行时检查绑定,你会看到这一点。

问题在于控制器并不知道插头关于字典的蹲下。它只知道IEnumerable<T>Dictionary<K,T>实现IEnumerable<KeyValuePair<K,T>>,因此控件会为每个键值对创建一个项目。 SelectedItem也是一个键值对。因此,当您将其绑定到类型UserRecord的属性时,是的,它能够使用SelectedValuePath正确设置值,但它不能(不)[忍者编辑:除非此行为已更改在过去的几年中:/]迭代枚举,以便在视图模型中设置值时找到正确的键值对

如果UserRecord的键值是该类型中的属性,那么肯定会为它创建一个KeyedCollection。 KeyedCollection<Tkey,TItem>实现了&#39; IEnumerable`,因此它可以与绑定无缝协作。如果没有,请将其包装在代理中,或添加属性。

当我说&#34;将它包装在代理中时,任何人都会说'&34;什么,比如KeyValuePair?&#34;我打算通过互联网打你。代理成为您绑定的值。不要浪费你的时间SelectedValuePath胡说八道。直接与代理人合作。当你需要你的值时,在最后一刻提取它,而不是在绑定执行后立即提取它。