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

时间:2013-07-10 14:25:56

标签: 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>

代码隐藏(这只是一个例子,我在完整的应用程序中使用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));

    }
}

2 个答案:

答案 0 :(得分: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();
    }

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

答案 1 :(得分:1)

我不确定您预计会发生什么,但您添加到AllBillingModels所有结算模式(one two three),它们是所有这些都显示在组合框中(平面,可变和自由)

修改

好的,如果你还在这里,我有一个好主意 对于您的ComboBox Xaml:

<StackPanel Orientation="Horizontal">
        <Label Content="Billing Model:"/>
        <ComboBox ItemsSource="{Binding AllBillingModels}" DisplayMemberPath="BillingModelDescription"
          SelectedItem="{Binding SelectedClient.BillingModel}"
                  Text="{Binding SelectedClient.BillingModel.BillingModelDescription}"
          Width="300"/>
</StackPanel>

这会更新组合框中的测试。