【问题标题】:Silverlight Combobox - Setting the SelectedItem MVVMSilverlight Combobox - 设置 SelectedItem MVVM
【发布时间】:2011-04-11 17:31:09
【问题描述】:

我有一个 ViewModel 设置“UserStructure”属性的值。问题是组合框不会绑定到值。

public class OwnerOccupierAccountViewModel : ViewModelBase
{
    /// <summary>
    /// Load combobox structures
    /// </summary>
    private readonly LoadOperation<Structure> _loadStructures;

    private readonly LoadOperation<UnitOccupierDetail> _loadUnitOccupierDetails;

    //public ICommand SaveAccountSettingsCommand { get; set; }

    #region Properties

    private ObservableCollection<Structure> _structures;
    public ObservableCollection<Structure> Structures
    {
        get { return _structures; }

        set
        {
            _structures = value;
            RaisePropertyChanged("Structures");
        }
    }

    private Structure _userStructure;
    public Structure UserStructure
    {
        get { return _userStructure; }
        set
        {
            _userStructure = value;
            RaisePropertyChanged("SelectedStructure");
        }
    }

    private UnitOccupierDetail _unitOccupierDetail;
    public UnitOccupierDetail UnitOccupierDetail
    {
        get { return _unitOccupierDetail; }
        set
        {
            _unitOccupierDetail = value;
            RaisePropertyChanged("UnitOccupierDetail");
        }
    }


    #endregion

    public OwnerOccupierAccountViewModel()
    {
        // SaveAccountSettingsCommand = new DelegateCommand(SaveAccountSettings, CanSave);

        UserAccountContext _userAccountContext;

        if (!DesignerProperties.IsInDesignTool)
        {
            var loggedInUser = new Guid(WebContext.Current.User.UserID.ToString());

            _userAccountContext = new UserAccountContext();

            #region load structures
            _loadStructures = _userAccountContext.Load(_userAccountContext.GetStructuresQuery());
            _loadStructures.Completed += _loadStructuresCompleted;
            #endregion

            #region load user data 
            _loadUnitOccupierDetails =
                _userAccountContext.Load(
                    _userAccountContext.GetUnitOccupierDetailsQuery().Where(
                        u => u.UserIDFK == loggedInUser && u.StructureFK == 92));
            _loadUnitOccupierDetails.Completed += _loadUnitOccupierDetails_Completed;
            #endregion
        }
    }

    void _loadUnitOccupierDetails_Completed(object sender, EventArgs e)
    {
        _unitOccupierDetail= new UnitOccupierDetail();
        _unitOccupierDetail = _loadUnitOccupierDetails.Entities.First();

        _userStructure = _unitOccupierDetail.Structure;
    }

    void _loadStructuresCompleted(object sender, EventArgs e)
    {
        var theseStructures = new ObservableCollection<Structure>(_loadStructures.Entities);
        Structures = theseStructures;
    }

    //private void SaveAccountSettings(object param)
    //{

    //}

    //private static bool CanSave(object param)
    //{
    //    return true;
    //}
}

 <ComboBox x:Name="cboApartments" 
                          ItemsSource='{Binding Structures, Mode=TwoWay}'
                          DisplayMemberPath='StructureName'
                          SelectedValuePath='IDStructure'
                          SelectedItem='{Binding SelectedStructure,Mode=TwoWay}'
                          Width="200"
                          Height="25">

【问题讨论】:

    标签: silverlight silverlight-4.0 mvvm


    【解决方案1】:

    在 xaml UserStructure 中改为 SelectedStructure。

    【讨论】:

      【解决方案2】:

      在你的 XAML 中,SelectedItem 被绑定到 SelectedStructure 而不是你想要的 UserStructure

      更新:

      您的代码不起作用,因为您应该设置为与 ItemsSource 中的某个对象具有引用相等性的 SelectedItem 对象。在您的 ViewModel 中,您将 Structures 设置为一项服务操作的结果,并将 UserStructure 设置为另一项服务操作的结果。 UserStructure 和 Structures 中的某些对象可以是等于 (object.Equals) 但不能是引用等于 (object.ReferenceEquals)。与其他 ItemsControls 一样,ComboBox 不会按相等性比较项目,而是按身份比较它们。因此,要获得正确的代码,您应该从等于 UserStructure 的 Structures 对象中选择并将其设置为 UserStructure:

         void _loadUnitOccupierDetails_Completed(object sender, EventArgs e)
         {
              ...
      
              Structure userStructure = Structures.FirstOrDefault(s=>s.Equals(_unitOccupierDetail.Structure));
              UserStructure = userStructure;
         }
      

      在这种情况下,您应该确保 Structures 出现在前面。您可以查看 Reactive Extensions Observable.ForkJoin() 方法来同步 2 个异步调用。

      【讨论】:

      • 是的,我已经更正了这一点,RaisePropertyChanged 事件......组合框仍然不会绑定
      • ItemsSource='{Binding Structures, Mode=TwoWay}':改用 ItemsSource='{Binding Structures}'
      • 替换 _userStructure = _unitOccupierDetail.Structure;到 UserStructure = _unitOccupierDetail.Structure;在视图模型中
      • 感谢弗拉基米尔 - 您推荐的更改之一使它工作!
      【解决方案3】:

      试试这样的改变

      public class OwnerOccupierAccountViewModel : ViewModelBase
      {
          /// <summary>
          /// Load combobox structures
          /// </summary>
          private readonly LoadOperation<Structure> _loadStructures;
      
          private readonly LoadOperation<UnitOccupierDetail> _loadUnitOccupierDetails;
      
          //public ICommand SaveAccountSettingsCommand { get; set; }
      
          #region Properties
      
          private ObservableCollection<Structure> _structures;
          public ObservableCollection<Structure> Structures
          {
              get { return _structures; }
      
              set
              {
                  _structures = value;
                  RaisePropertyChanged("Structures");
              }
          }
      
          private Structure _userStructure;
          public Structure UserStructure
          {
              get { return _userStructure; }
              set
              {
                  _userStructure = value;
                  RaisePropertyChanged("UserStructure");
              }
          }
      
          private UnitOccupierDetail _unitOccupierDetail;
          public UnitOccupierDetail UnitOccupierDetail
          {
              get { return _unitOccupierDetail; }
              set
              {
                  _unitOccupierDetail = value;
                  RaisePropertyChanged("UnitOccupierDetail");
              }
          }
      
      
          #endregion
      
          public OwnerOccupierAccountViewModel()
          {
              // SaveAccountSettingsCommand = new DelegateCommand(SaveAccountSettings, CanSave);
      
              UserAccountContext _userAccountContext;
      
              if (!DesignerProperties.IsInDesignTool)
              {
                  var loggedInUser = new Guid(WebContext.Current.User.UserID.ToString());
      
                  _userAccountContext = new UserAccountContext();
      
                  #region load structures
                  _loadStructures = _userAccountContext.Load(_userAccountContext.GetStructuresQuery());
                  _loadStructures.Completed += _loadStructuresCompleted;
                  #endregion
      
                  #region load user data 
                  _loadUnitOccupierDetails =
                      _userAccountContext.Load(
                          _userAccountContext.GetUnitOccupierDetailsQuery().Where(
                              u => u.UserIDFK == loggedInUser && u.StructureFK == 92));
                  _loadUnitOccupierDetails.Completed += _loadUnitOccupierDetails_Completed;
                  #endregion
              }
          }
      
          void _loadUnitOccupierDetails_Completed(object sender, EventArgs e)
          {
              _unitOccupierDetail= new UnitOccupierDetail();
              _unitOccupierDetail = _loadUnitOccupierDetails.Entities.First();
      
              _userStructure = _unitOccupierDetail.Structure;
          }
      
          void _loadStructuresCompleted(object sender, EventArgs e)
          {
              var theseStructures = new ObservableCollection<Structure>(_loadStructures.Entities);
              Structures = theseStructures;
          }
      
          //private void SaveAccountSettings(object param)
          //{
      
          //}
      
          //private static bool CanSave(object param)
          //{
          //    return true;
          //}
      }
      
       <ComboBox x:Name="cboApartments" 
                                ItemsSource='{Binding Structures, Mode=TwoWay}'
                                DisplayMemberPath='StructureName'
                                SelectedValuePath='IDStructure'
                                SelectedItem='{Binding UserStructure,Mode=TwoWay}'
                                Width="200"
                                Height="25">
      

      更新:

      嗯,也许在这里尝试更改:

           <ComboBox x:Name="cboApartments" 
                                    ItemsSource='{Binding Structures, Mode=TwoWay}'
                                    SelectedItem='{Binding UserStructure, Mode=TwoWay}'
                                    Width="200"
                                    Height="25">
                  <ComboBox.ItemTemplate>
                      <DataTemplate>
                          <TextBlock Text="{Binding Path=StructureName}"/>
                      </DataTemplate>
                  </ComboBox.ItemTemplate>
              </ComboBox>
      

      【讨论】:

      • 嗨 Pawel - 我做了 2 处更正: RaisePropertyChanged("UserStructure");和 SelectedItem='{Binding UserStructure,Mode=TwoWay}' .... 组合框不会绑定
      • 我为您的问题添加了新提案
      • 嗨 Pawel - 我用你的代码替换了组合框 - 仍然没有绑定
      • 澄清一下,combox 绑定了初始值,但 UserStructure 属性未绑定到选定项。
      • 嗯,所以在您更改组合框中的选择后,UserStructure 属性不会改变?尝试直接绑定到 UnitOccupierDetail.Structure,而不是绑定到 UserStructure。 SelectedItem='{绑定 UnitOccupierDetail.Structure, Mode=TwoWay}'
      猜你喜欢
      • 1970-01-01
      • 2012-06-19
      • 1970-01-01
      • 1970-01-01
      • 2016-09-25
      • 2017-02-20
      • 1970-01-01
      • 2015-03-13
      • 2014-03-18
      相关资源
      最近更新 更多