ComboBox上的SelectedItem

时间:2013-06-13 01:50:32

标签: wpf combobox selecteditem

应用程序中有一个ComboBox绑定到一组项目。有些情况下,用户可以从ComboBox中选择一个项目,但所选项目可能还没有准备就绪,因此ComboBox所选项目必须返回到上一个选定项目(或集合中的其他项目) ),但在当前应用程序中ComboBox始终显示用户选择的项目,而不是在设置它并调用通知属性更改后检索有效项目。

流动是一个简化的代码,显示了问题。

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private List<Customer> _Customers = new List<Customer>();

    public List<string> CustomerNames
    {
        get
        {
            var list = new List<string>();
            foreach (var c in _Customers)
            {
                list.Add(c.Name);
            }
            return list; ;
        }
    }

    public string CustomerName
    {
        get
        {
            var customer = _Customers.Where(c => c.IsReady).FirstOrDefault();
            return customer.Name;
        }
        set
        {
            NotifyPropertyChanged("CustomerName");
        }
    }

    public MainWindow()
    {
        SetupCustomers();
        InitializeComponent();
        this.DataContext = this;
    }

    private void SetupCustomers()
    {
        _Customers.Add(new Customer("c1", true));
        _Customers.Add(new Customer("c2", false));
        _Customers.Add(new Customer("c3", false));
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

public class Customer
{
    public Customer(string name, bool isReady)
    {
        this.Name = name;
        this.IsReady = isReady;
    }

    public bool IsReady { get; set; }

    public string Name { get; set; }

    public override bool Equals(object obj)
    {
        return base.Equals(obj);
    }
    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}    


<Window x:Class="TryComboboxReset.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">
<Grid>

    <ComboBox   Width="100"
                Height="25"
                ItemsSource="{Binding Path=CustomerNames, Mode=OneWay}"
                SelectedItem="{Binding Path=CustomerName, Mode=TwoWay}"/>

</Grid>

2 个答案:

答案 0 :(得分:1)

问题是UI线程,我使用调度程序来解决这个问题

 public partial class MainWindow : Window, INotifyPropertyChanged
{
    private ObservableCollection<Customer> _Customers =
        new ObservableCollection<Customer>();

    public ObservableCollection<Customer> CustomerNames
    {
        get
        {
            return _Customers;
        }
    }

    public Customer CustomerName
    {
        get
        {
            return _Customers.Where(c => c.IsReady == true).FirstOrDefault();
        }
        set
        {
            // Delay the revert
            Application.Current.Dispatcher.BeginInvoke(
                new Action(() => NotifyPropertyChanged("CustomerName")), DispatcherPriority.ContextIdle, null);
        }
    }

    public MainWindow()
    {
        SetupCustomers();
        InitializeComponent();
        this.DataContext = this;
    }

    private void SetupCustomers()
    {
        _Customers.Add(new Customer("c1", true));
        _Customers.Add(new Customer("c2", false));
        _Customers.Add(new Customer("c3", false));
        CustomerName = _Customers.Where(c => c.IsReady == true).FirstOrDefault();
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

public class Customer
{
    public Customer(string name, bool isReady)
    {
        this.Name = name;
        this.IsReady = isReady;
    }

    public bool IsReady { get; set; }

    public string Name { get; set; }
}   

<ComboBox   Width="400"
            Height="25"
            ItemsSource="{Binding Path=CustomerNames}"
            SelectedValue="{Binding CustomerName,Mode=TwoWay}"    >
       <ComboBox.ItemTemplate>
             <DataTemplate>
                 <TextBlock Text="{Binding Name}"/>
             </DataTemplate>
        </ComboBox.ItemTemplate>
 </ComboBox>

答案 1 :(得分:0)

您实际上并未在设置器中设置所选客户名称的值,并且您的getter总是会返回第一个&#34; ready&#34;它找到的客户名称......

如果我正确理解问题,你需要做更多的事情:

private string _customerName = null;

public string CustomerName
    {
        get
        {
            if(_customerName == null) 
            {
                _customerName = _Customers.Where(c => c.IsReady).FirstOrDefault().Name;
            }
            return _customerName;
        }
        set
        {
            _customerName = value;
            NotifyPropertyChanged("CustomerName");
        }
    }