WPF MVVM组合框SelectedItem或SelectedValue不工作

WPF MVVM组合框SelectedItem或SelectedValue不工作,wpf,mvvm,combobox,Wpf,Mvvm,Combobox,更新 经过一点调查。问题似乎是SelectedValue/SelectedItem在项目源加载完成之前发生。如果我坐在一个断点上等待几秒钟,它就会像预期的那样工作。我不知道我该怎么避开这个 结束更新 我有一个应用程序在WPF中使用MVVM和一个组合框。下面是ViewModel示例。我遇到的问题是,当我们离开页面并迁移回时,组合框没有选择当前选择的值 查看模型 公共类MyViewModel { 私有MyObject_selectedObject; 私人收藏对象; 私有IModel_模型; 公共My

更新

经过一点调查。问题似乎是SelectedValue/SelectedItem在项目源加载完成之前发生。如果我坐在一个断点上等待几秒钟,它就会像预期的那样工作。我不知道我该怎么避开这个

结束更新

我有一个应用程序在WPF中使用MVVM和一个组合框。下面是ViewModel示例。我遇到的问题是,当我们离开页面并迁移回时,组合框没有选择当前选择的值

查看模型

公共类MyViewModel
{
私有MyObject_selectedObject;
私人收藏对象;
私有IModel_模型;
公共MyViewModel(IModel模型)
{
_模型=模型;
_objects=_model.GetObjects();
}
公共收集对象
{
得到
{
返回_对象;
}
专用设备
{
_对象=价值;
}
}
公共MyObject Selected对象
{
得到
{
返回_selectedObject;
}
设置
{
_selectedObject=值;
}
}
}
在本例中,假设MyObject有两个属性(Text和Id)。组合框的XAML如下所示

XAML


无论我以何种方式配置,当我返回页面并重新组装对象时,组合框都不会选择该值。但是,对象通过属性中的get返回正确的对象


我不确定这是否只是ComboBox和MVVM模式工作方式的问题。我们正在进行的文本框绑定工作正常。

您是否尝试在viewmodel中实现
INotifyPropertyChanged
,然后在设置
SelectedItem
时引发
PropertyChanged
事件


如果这本身无法修复它,那么您可以在导航回页面时自己手动引发
PropertyChanged
事件,这应该足以让WPF重新绘制自己并显示正确的选定项。

我也遇到过类似的问题,通过确保正确实施了IEquatable,问题得到了解决。当绑定发生时,它会尝试查看对象是否匹配,因此请确保正确执行了相等性检查。

我以前也注意到过这种行为。我注意到SelectedIndex属性不会导致相同的错误。如果您可以重新构造ViewModel以公开所选项目的索引,并绑定到该索引,那么您就可以开始了。

这可能是您将DataContext应用到页面的方式。在WPF中,每次您导航到一个页面时,所有内容都会被重新初始化、调用构造函数、加载方法等等。因此,如果您在视图中设置DataContext,那么毫无疑问,您将清除用户选择的SelectedItem。为了避免这种情况,请使用页面的KeepAlive属性

<Page KeepAlive="True" ...>
   ...
</Page>

...
这将导致在导航回您已经访问过的页面时仅触发加载的事件。因此,您需要确保在初始化时设置DataContext(外部或构造函数内部),而不是在加载时


但是,这仅适用于该页面实例。如果您导航到该页面的新实例,它将再次被调用。

我也遇到了同样的问题。事情是这样的。选定项不知道应从集合中使用哪个对象。因此,您必须向所选项目说明如何使用集合中的项目

public MyObject SelectedObject
 {
      get
      {
          Objects.find(x => x.id == _selectedObject.id)
          return _selectedObject;
      }
      set
      {
           _selectedObject = value;
      }
 }

我希望这会有所帮助。

ComboBox.SelectionBoxItem.ToString()

IsSyncronizedWithCurrent=False将使其工作。

您需要将ItemsSource属性放在SelectedItem属性之前。几天前,我在博客中提到了这个问题。

使用加载的事件:

private void cmb_Loaded(object sender, RoutedEventArgs e) {
    if (cmb.Items.Count > 0) cmb.SelectedIndex = 0;          
}

这对我很有用。

我为这个问题争论了一段时间。在我的例子中,我使用In-complex-type(List)作为项目源,并使用KeyType作为所选值。在load事件中,KeyType被设置为null。这使一切都破裂了。当键更改时,所有子元素都不会更新。事实证明,当我添加一个检查以确保KeyType的建议值不为null时,一切都按预期进行

    #region Property: SelectedKey
    // s.Append(string.Format("SelectedKey : {0} " + Environment.NewLine, SelectedKey.ToString()));

    private KeyType _SelectedKey = new KeyType();
    public KeyType SelectedKey
    {
        get { return _SelectedKey; }
        set
        {
            if(value != null )
                if (!_SelectedKey.Equals(value))
                {
                    _SelectedKey = value;
                    OnPropertyChanged("SelectedKey");
                }
        }
    }
    #endregion SelectedKey

离开当前页面时,与组合框的
ItemsSource
属性关联的
CollectionView
将被清除。而且由于默认情况下,
组合框
与当前
属性同步,因此,
SelectedItem
SelectedValue
属性被重置。
这似乎是绑定中的内部数据类型问题。正如上面其他人所建议的,如果您通过绑定到viewmodel上的int属性而使用
SelectedValue
,它将起作用。 一个快捷方式是覆盖MyObject上的
Equals
操作符,以便在比较两个MyObject时,比较实际的
Id
属性


另一个提示:如果确实重新构造viewmodels并使用
SelectedValue
,则仅当
SelectedValuePath=Id
其中
Id
int
时才使用它。如果使用字符串键,请绑定到组合框的
文本属性,而不是
SelectedValue

SelectedValuePath
SelectedValue
的类型必须完全相同

例如,如果
SelectedValuePath
的类型为
Int16
,而绑定到
SelectedValue
的属性类型为
int
,则它将不起作用

我花了几个小时去寻找,这就是为什么我
    #region Property: SelectedKey
    // s.Append(string.Format("SelectedKey : {0} " + Environment.NewLine, SelectedKey.ToString()));

    private KeyType _SelectedKey = new KeyType();
    public KeyType SelectedKey
    {
        get { return _SelectedKey; }
        set
        {
            if(value != null )
                if (!_SelectedKey.Equals(value))
                {
                    _SelectedKey = value;
                    OnPropertyChanged("SelectedKey");
                }
        }
    }
    #endregion SelectedKey
    public Role SelectedObject 
    {
        get { return object; }
        set
        {
            if (value != null)
            {
                if (!object.Equals(value))
                {
                    object = value;
                    OnPropertyChanged(() => SelectedObject );
                }
            }
        }
    }
public class EqualityBrush
{
    public SolidColorBrush Brush { get; set; }

    public override bool Equals(object o)
    {
        if (o is EqualityBrush)
        {
            SolidColorBrush b = ((EqualityBrush)o).Brush;
            return b.Color.R == this.Brush.Color.R && b.Color.G == this.Brush.Color.G && b.Color.B == this.Brush.Color.B;
        }
        else
            return false;
    }
}
<ComboBox ItemsSource="{Binding BuerkertBrushes}" SelectedItem="{Binding Brush, Mode=TwoWay}" Width="40">
    <ComboBox.Resources>
        <DataTemplate DataType="{x:Type tree:EqualityBrush}">
            <Rectangle Width="20" Height="12" Fill="{Binding Brush}"/>
        </DataTemplate>
    </ComboBox.Resources>
</ComboBox>
<ctrls:ComboBoxControlBase SelectedItem="{Binding Path=SelectedProfile, Mode=TwoWay}" ItemsSource="{Binding Path=Profiles, Mode=OneWay}" IsEditable="False" DisplayMemberPath="Name" />
public ObservableCollection<Profile> Profiles
{
   get { return this.profiles; }
   private set { profiles = value; RaisePropertyChanged("Profiles"); }
}
public Profile SelectedProfile 
{
    get { return selectedProfile; }
    set
    {
        if (this.SelectedUser != null)
        {
            this.SelectedUser.Profile = value; 
            RaisePropertyChanged("SelectedProfile");  
        } 
    } 
}
    [Command("SelectionChanged")]
    public void SelectionChanged(User selectedUser)
    {
        if (selectedUser != null)
        {
            if (selectedUser is User)
            {
                if (selectedUser.Profile != null)
                {
                    this.SelectedUser = selectedUser;
                    this.selectedProfile = this.Profiles.Where(p => p.Id == this.SelectedUser.Profile.Id).FirstOrDefault();
                    MessageBroker.Instance.NotifyColleagues("ShowItemDetails"); 
                }
            }
        }            
    }
 Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
 {
     combobox.SelectedIndex = 0;
 }));
        public int SelectedIndex
        {
            get { return _selectedIndex; }
            set
            {
                _selectedIndex = value;
                OnPropertyChanged();
            }    
        }
<ComboBox SelectedIndex="{Binding SelectedIndex,Mode=TwoWay}" ... >