Wpf 在组合框上选择编辑项

Wpf 在组合框上选择编辑项,wpf,combobox,selecteditem,Wpf,Combobox,Selecteditem,应用程序中有一个绑定到项目集合的组合框。在某些情况下,用户可以从组合框中选择项目,但所选项目可能尚未准备就绪,因此组合框所选项目必须返回到上一个所选项目(或集合中的其他项目),但是在当前应用程序中,组合框始终显示从用户处选择的项目,而不是在设置并调用notify property change后检索有效项目 flow是一个简化的代码,它显示了这个问题 public partial class MainWindow : Window, INotifyPropertyChanged { pr

应用程序中有一个绑定到项目集合的组合框。在某些情况下,用户可以从
组合框
中选择项目,但所选项目可能尚未准备就绪,因此
组合框
所选项目必须返回到上一个所选项目(或集合中的其他项目),但是在当前应用程序中,
组合框
始终显示从用户处选择的项目,而不是在设置并调用notify property change后检索有效项目

flow是一个简化的代码,它显示了这个问题

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>
public分部类主窗口:窗口,INotifyPropertyChanged
{
私人列表_客户=新列表();
公共列表客户名称
{
得到
{
var list=新列表();
foreach(客户的var c)
{
列表。添加(c.名称);
}
退货清单;
}
}
公共字符串客户名称
{
得到
{
var customer=_Customers.Where(c=>c.IsReady.FirstOrDefault();
返回客户名称;
}
设置
{
NotifyPropertyChanged(“客户名称”);
}
}
公共主窗口()
{
设置客户();
初始化组件();
this.DataContext=this;
}
私人客户()
{
_添加(新客户(“c1”,真));
_添加(新客户(“c2”,假));
_添加(新客户(“c3”,假));
}
公共事件属性更改事件处理程序属性更改;
受保护的void NotifyPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
公共类客户
{
公共客户(字符串名称,bool isReady)
{
this.Name=Name;
this.IsReady=IsReady;
}
公共bool已就绪{get;set;}
公共字符串名称{get;set;}
公共覆盖布尔等于(对象对象对象)
{
返回基数等于(obj);
}
公共覆盖int GetHashCode()
{
返回base.GetHashCode();
}
}    

您实际上没有在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");
        }
    }

实际上,您并没有在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");
        }
    }

问题是UI线程,我使用dispatcher解决了这个问题

 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>
public分部类主窗口:窗口,INotifyPropertyChanged
{
私人可观测收集客户=
新的可观察集合();
公共可观测集合客户名称
{
得到
{
退回客户;
}
}
公共客户名称
{
得到
{
return _Customers.Where(c=>c.IsReady==true).FirstOrDefault();
}
设置
{
//延迟恢复
Application.Current.Dispatcher.BeginInvoke(
新操作(()=>NotifyPropertyChanged(“CustomerName”)),DispatcherPriority.ContextIdle,null);
}
}
公共主窗口()
{
设置客户();
初始化组件();
this.DataContext=this;
}
私人客户()
{
_添加(新客户(“c1”,真));
_添加(新客户(“c2”,假));
_添加(新客户(“c3”,假));
CustomerName=_Customers.Where(c=>c.IsReady==true).FirstOrDefault();
}
公共事件属性更改事件处理程序属性更改;
受保护的void NotifyPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
公共类客户
{
公共客户(字符串名称,bool isReady)
{
this.Name=Name;
this.IsReady=IsReady;
}
公共bool已就绪{get;set;}
公共字符串名称{get;set;}
}   

问题是UI线程,我使用dispatcher解决了这个问题

 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>
public分部类主窗口:窗口,INotifyPropertyChanged
{
私人可观测收集客户=
新的可观察集合();
公共可观测集合客户名称
{
得到
{
退回客户;
}
}
公共客户名称
{
得到
{
return _Customers.Where(c=>c.IsReady==true).FirstOrDefault();
}
设置
{
//延迟恢复
Application.Current.Dispatcher.BeginInvoke(
新操作(()=>NotifyPropertyChanged(“CustomerName”)),DispatcherPriority.ContextIdle,null);
}
}
公共主窗口()
{
设置客户();
初始化组件();
this.DataContext=this;
}
私人客户()
{
_添加(新客户(“c1”,真));
_添加(新客户(“c2”,假));
_添加(新客户(“c3”,假));
CustomerName=_Customers.Where(c=>c.IsReady==true).FirstOrDefault();
}
公共事件属性更改事件处理程序属性更改;
受保护的void NotifyPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
公共类客户
{
公共客户(字符串名称,bool isReady)
{
这是我的名字=