【问题标题】:SelectedItem on ComboBox组合框上的选定项
【发布时间】:2013-06-09 07:19:16
【问题描述】:

应用程序中有一个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>

【问题讨论】:

    标签: wpf combobox selecteditem


    【解决方案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>
    

    【讨论】:

      【解决方案2】:

      您实际上并没有在您的 setter 中设置所选客户名称的值,您的 getter 总是会返回它找到的第一个“就绪”客户名称...

      如果我对问题的理解正确,您需要按照以下方式做更多的事情:

      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");
              }
          }
      

      【讨论】:

      • 这是故意的,正如我在问题中提到的客户未准备好时不应设置它,例如在此示例中,当用户从组合框中选择“C2”时,设置器将设置所选客户必须回到“C1”(在这个例子中,只有“C1”准备好了,这是为了让代码更容易阅读)但是当我运行应用程序时,即使setter选择了“C1”并且getter返回它但是Combobox显示“C2”作为选中项。
      猜你喜欢
      • 2013-01-14
      • 1970-01-01
      • 1970-01-01
      • 2010-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多