为什么WPF ComboBox项目没有更新?

The*_*fen 1 c# wpf binding combobox selecteditem

我不明白为什么在我的以下示例中,"Billing Model"组合框在文本框中没有显示属性BillingModel.BillingModelDescription.选择客户端后,我希望组合框显示当前的billng模型描述,但它保持空白.绑定到同一事物的文本框确实显示了描述.我有一些可能的模型作为ItemsSource,它工作正常.如何在选择客户端时更新计费模型组合框?

这是XAML:

<Window x:Class="WpfApplication7.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<StackPanel>
    <StackPanel Orientation="Horizontal">
        <Label Content="Client"/>
    <ComboBox ItemsSource="{Binding AllClientData}" DisplayMemberPath="EmployerStr"
              SelectedItem="{Binding SelectedClient}"
              Width="300"/>
    </StackPanel>
    <StackPanel Orientation="Horizontal">
        <Label Content="Billing Model:"/>
    <ComboBox ItemsSource="{Binding AllBillingModels}" DisplayMemberPath="BillingModelDescription"
              SelectedItem="{Binding SelectedClient.BillingModel}"
              Width="300"/>
    </StackPanel>
    <StackPanel Orientation="Horizontal">
        <Label Content="Billing Model" />
    <TextBox Text="{Binding SelectedClient.BillingModel.BillingModelDescription}" Width="200"/>
    </StackPanel>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

代码隐藏(这只是一个例子,我在完整的应用程序中使用MVVM等,但这是我用来说明问题):

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        AllClientData = new ObservableCollection<ClientRate>();
        AllBillingModels = new ObservableCollection<BillingModelType>();

        ClientRate uno = new ClientRate();
        uno.BillingModel = new BillingModelType();
        uno.BillingModel.BillingModelID = 3;
        uno.BillingModel.BillingModelDescription = "Free";
        uno.ID = 01;
        uno.EmployerName = "Employer1";

        ClientRate dos = new ClientRate();
        dos.BillingModel = new BillingModelType();
        dos.BillingModel.BillingModelID = 2;
        dos.BillingModel.BillingModelDescription = "Variable";
        dos.ID = 02;
        dos.EmployerName = "Employer2";

        ClientRate tre = new ClientRate();
        tre.BillingModel = new BillingModelType();
        tre.BillingModel.BillingModelID = 1;
        tre.BillingModel.BillingModelDescription = "Flat";
        tre.ID = 01;
        tre.EmployerName = "Employer3";

        AllClientData.Add(uno);
        AllClientData.Add(dos);
        AllClientData.Add(tre);

        BillingModelType one = new BillingModelType();
        one.BillingModelID = 1;
        one.BillingModelDescription = "Flat";

        BillingModelType two = new BillingModelType();
        two.BillingModelID = 2;
        two.BillingModelDescription = "Variable";

        BillingModelType three = new BillingModelType();
        three.BillingModelID = 3;
        three.BillingModelDescription = "Free";

        AllBillingModels.Add(one);
        AllBillingModels.Add(two);
        AllBillingModels.Add(three);

        InitializeComponent();
        this.DataContext = this;
    }

    private ObservableCollection<ClientRate> _allClientData;
    public ObservableCollection<ClientRate> AllClientData
    {
        get { return _allClientData; }
        set
        {
            if (_allClientData != value)
            {
                _allClientData = value;
                FirePropertyChanged("AllClientData");
            }
        }
    }

    private ClientRate _selectedClient;
    /// <summary>
    /// Gets/Sets Global SelectedClient object
    /// </summary>
    public ClientRate SelectedClient
    {
        get { return _selectedClient; }
        set
        {
            if (_selectedClient != value)
            {
                _selectedClient = value;
                FirePropertyChanged("SelectedClient");
            }
        }
    }

    //private BillingModelType _selectedBillingModel;
    //public BillingModelType SelectedBillingModel
    //{
    //    get
    //    {
    //        return _selectedBillingModel;
    //    }
    //    set
    //    {
    //        if (_selectedBillingModel != value)
    //        {
    //            _selectedBillingModel = value;
    //            FirePropertyChanged("SelectedBillingModel");
    //        }
    //    }
    //}

    private ObservableCollection<BillingModelType> _allBillingModels;
    /// <summary>
    /// Holds all possible billing model types 
    /// </summary>
    public ObservableCollection<BillingModelType> AllBillingModels
    {
        get { return _allBillingModels; }
        set
        {
            if (_allBillingModels != value)
            {
                _allBillingModels = value;
                FirePropertyChanged("AllBillingModels");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void FirePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

    }
}

public class BillingModelType
{
    /// <summary>
    /// Billing Model ID
    /// </summary>
    public int? BillingModelID { get; set; }
    /// <summary>
    /// Billing Model Description
    /// </summary>
    public string BillingModelDescription { get; set; }
}

public class ClientRate : INotifyPropertyChanged
{
    /// <summary>
    /// Employer name with Employer ID in parentheses
    /// </summary>
    public string EmployerStr { get { return EmployerName + " (" + ID + ")"; } }
    /// <summary>
    /// Employer ID
    /// </summary>
    public int? ID { get; set; }
    private string _EmployerName;
    /// <summary>
    /// Employer Official Name
    /// </summary>
    public string EmployerName
    {
        get { return _EmployerName; }
        set
        {
            if (_EmployerName != value)
            {
                _EmployerName = value;
                FirePropertyChanged("EmployerName");
            }
        }
    }

    private BillingModelType _billingModel;
    /// <summary>
    /// Rate Type  ID and Description
    /// </summary>
    public BillingModelType BillingModel
    {
        get { return _billingModel; }
        set
        {
            if (_billingModel != value)
            {
                _billingModel = value;
                FirePropertyChanged("BillingModel");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void FirePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

    }
}
Run Code Online (Sandbox Code Playgroud)

The*_*fen 5

我通过覆盖我的BillingModelType类中的Equals()来修复此问题.正如我所怀疑的那样,问题是BillingModel与可能选择列表中使用的BillingModel实例不完全相同.所以我简单地说:

public override bool Equals(object obj)
    {
        if (obj == null || !(obj is BillingModelType))
            return false;
        return ((BillingModelType)obj).BillingModelID == this.BillingModelID;
    }

public override int GetHashCode()
    {
        return this.BillingModelID.GetHashCode();
    }
Run Code Online (Sandbox Code Playgroud)

到BillingModelTypes的类,一切都很好.感谢Rachel Lim,因为我在这里找到了关于这个问题的博客:http: //rachel53461.wordpress.com/2011/08/20/comboboxs-selecteditem-not-displaying/#comments

  • 嗨 Theo,要使用 `SelectedValue` 和 `SelectedValuePath`,您首先将 `SelectedValuePath` 设置为等于您的项目标识符的字符串(在您的情况下,`SelectedValuePath="BillingModelID"`),然后您将绑定`SelectedValue` 到所选项目的 Id (`SelectedValue="{Binding SelectedClient.BillingModelID}"`)。要做到这一点,您可能需要稍微更改您的“SelectedClient”模型,因为我认为绑定到“SelectedValue="{Binding SelectedClient.BillingModel.BillingModelID}"”将无法正常工作。不过我可能是错的,所以尝试它不会有什么坏处。 (2认同)