【问题标题】:XAML WinRT ComboBox Set SelectedItemXAML WinRT ComboBox 设置 SelectedItem
【发布时间】:2015-01-19 19:55:41
【问题描述】:

我有一个绑定到 ObservableList 的组合框(可观察列表继承自 ObservableCollection)。这是我的 Carrier 对象:

public class Carrier
{
    /// <summary>
    /// The carrier's name as it should be displayed to customers
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// This is the domain that email-to-text messages should be sent to. 
    /// </summary>
    public string TextBase { get; set; }

    /// <summary>
    /// Unique identifier for carriers
    /// </summary>
    public int CarrierId { get; set; }
}

我的问题是,在我的 ViewModel 中,我试图设置所选项目的值,但它没有在 UI 中设置。当我从组合框中选择一个选项时,它会正确修改我的视图模型(所以我知道绑定正在工作)。

这是我的 xaml:

                <ComboBox ItemsSource="{Binding ElementName=UserInformationPage, Path=DataContext.PhoneCarriers}" 
                      Style="{StaticResource ComboBox}"
                      Width="250"
                      DisplayMemberPath="Name"
                      SelectedItem="{Binding Path=SelectedCarrier, Mode=TwoWay}"
                      SelectedValuePath="CarrierId"
                      />

这是我的视图模型:

    public Carrier SelectedCarrier
    {
        get { return _selectedCarrier != null ? PhoneCarriers.First(c => c.CarrierId == _selectedCarrier.CarrierId) : PhoneCarriers.First(); }
        set
        {
            if (_selectedCarrier == null || _selectedCarrier.CarrierId != value.CarrierId)
            {
                Set(ref _selectedCarrier, value);
                if (User != null)
                    User.Phone.Carrier = value;
            }
        }
    }

    public UserDemographicsViewModel()
    {
        MessengerInstance.Register<SelectedUser>(this, m =>
        {
            User = m.User;
            CheckCanShowPassword();
            CheckCanResetPassword();
        });

        NavigationService.Navigated += (s, e) =>
        {
            if (e.Parameter is User)
            {
                User = e.Parameter as User;
                if (User.Phone != null)
                {
                    SelectedCarrier = User.Phone.Carrier;
                }
            }
        };

        IsPasswordTextShown = false;
        TogglePasswordCommand = new RelayCommand(() => IsPasswordTextShown = !IsPasswordTextShown); //flip the state of password shown
        SaveUserCommand = new RelayCommand<User>(SaveUser, u => CanSaveUser());
        ResetPasswordCommand = new RelayCommand(TryResetPassword, () => User != null && User.UserId != 0); //we have a user and its not a new user



        var repo = IoCContainer.GetContainer().Resolve<IAccountRepository>();
        var loggedInUser = App.Session.Get<User>("AuthenticatedUser");
        PhoneCarriers = new ObservableList<Carrier>(repo.GetPhoneCarriers(loggedInUser.AccountId));

    }

正如我所说,我知道我已正确绑定到 SelectedCarrier 属性,但由于某种原因,当 SelectedCarrier 与 PhoneCarriers 集合中的值匹配时,下拉列表中的值显示为空白。

更新

我尝试使用以下内容简化我的 SelectedCarrier 属性:

    public Carrier SelectedCarrier
    {
        get { return _selectedCarrier; }
        set
        {
            if (_selectedCarrier == null || _selectedCarrier.CarrierId != value.CarrierId)
            {
                _selectedCarrier = value;
                RaisePropertyChanged("SelectedCarrier");
                if (User != null)
                    User.Phone.Carrier = value;
            }
        }
    }

我知道我有一个选定的运营商,因为在调试时,如果我更改下拉值,我可以在 _selectedCarrier 更改为新值之前看到它的值(并且它很好地击中断点)。该值只是不显示在用户界面中。

【问题讨论】:

  • 同时设置 ItemsSource 和 SelectedItem 在 XAML 中是一个出了名的问题。顺序需要正确,您设置的其他属性可能也会对其产生影响。

标签: c# xaml combobox windows-runtime


【解决方案1】:

所以问题与我的 xaml 有关,但我不确定为什么它不起作用。当我改变时:

<ComboBox ItemsSource="{Binding ElementName=UserInformationPage, Path=DataContext.PhoneCarriers}" 
                  Style="{StaticResource ComboBox}"
                  Width="250"
                  DisplayMemberPath="Name"
                  SelectedItem="{Binding Path=SelectedCarrier, Mode=TwoWay}"
                  SelectedValuePath="CarrierId"
                  />

到:

<ComboBox ItemsSource="{Binding PhoneCarriers}" 
                      Style="{StaticResource ComboBox}"
                      Width="500"
                      SelectedValuePath="CarrierId"
                      DisplayMemberPath="Name"
                      SelectedItem="{Binding SelectedCarrier, Mode=TwoWay}"

                      />

它开始在加载时在下拉列表中显示 SelectedItem。

【讨论】:

  • 我遇到了一个类似的问题,它不会选择加载的项目。最初我将“ItemsSource”作为组合框元素上最后定义的属性,但它不起作用,所以我更改了它并将它放在开头,它可以工作吗?
【解决方案2】:

我会尝试简化代码,以查看它是否适用于仅使用支持字段而没有任何附加逻辑的简单属性。我假设您的 Set() 方法可以很好地引发更改通知。

我怀疑您设置的运营商与您获得的运营商不同,我不知道绑定在内部如何工作的所有细节,但我怀疑这可能是一个问题如果您设置的内容与您立即获得的内容不同。在 setter 和 getter 中放置断点,并确保绑定在设置后尝试获取新值。也许这些可能是不同的实例,但类型可能需要覆盖 Equals() 和 GetHashCode() 方法,以便来自不同来源的实例看起来相同。总体而言,将逻辑放入可绑定属性 getter 中而不是简单地访问支持字段是一个冒险的举动。

【讨论】:

  • 谢谢菲利普。我简化了我的 getter/setter 逻辑,但仍然看不到 UI 中设置的属性。我已经用新代码更新了我的问题。
  • 看起来我能够解决这个问题,虽然我仍然不明白我所做的更改是如何解决它的。
猜你喜欢
  • 2023-03-09
  • 1970-01-01
  • 2017-08-06
  • 1970-01-01
  • 1970-01-01
  • 2014-05-30
  • 2011-06-24
  • 2011-02-23
  • 1970-01-01
相关资源
最近更新 更多