组合框选定索引-1绑定到集合视图源

时间:2014-10-29 19:01:39

标签: c# xaml mvvm

我有一个ComboBox绑定到CollectionViewSource,我希望默认选择的索引应该是-1(因为什么都不应该被选中)我设置了SelectedIndex =“ - 1” 并且仍然选择了第一个项目。为什么呢?

我的观点xaml:

 <Window.Resources>
    <CollectionViewSource x:Key="States" Source="{Binding States}"/>
    <CollectionViewSource x:Key="Cities" Source="{Binding Source={StaticResource States}, Path=Cities}"/>
</Window.Resources>


             <ComboBox  SelectedValue="{Binding Person.State}" Width="150"  SelectedValuePath="StateInitial"  DisplayMemberPath="StateName" ItemsSource="{Binding Source={StaticResource States}}"/>
        <ComboBox SelectedValue="{Binding Person.City}" Width="150" SelectedValuePath="CityId" DisplayMemberPath="CityName" ItemsSource="{Binding Source={StaticResource Cities}}"/>

模型c#

 public class State 
{
    public State(string stateInitial, string stateName, ICollection<City> cities)
    {
        StateInitial = stateInitial;
        StateName = stateName;
        Cities = cities;

    }

    public string StateInitial { get; set; }
    public string StateName { get; set; }
    public virtual ICollection<City> Cities { get; set; }



}
public class City
{
    public int CityId { get; set; }
    public string CityName {get;set;}


}
public class Person : INotifyPropertyChanged
{
    #region Fields
    private string state;
    private int city;
    #endregion

    public string State
    {
        get
        { 
            return state; 
        }
        set
        {
            state = value;
            OnPropertyChanged("State");
        }

    }

    public int CityId
    {
        get
        {
            return city;
        }
        set
        {
            city = value;
            OnPropertyChanged("City");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));

        }
    }


}

ViewModel c#

   public  class MainWindowViewModel
{
    public Person NewPerson { get; set; }
    public List<State> States { get; private set; }

    public MainWindowViewModel()
    {
        States = GetStates();
        NewPerson = new Person();
    }
    public List<State> GetStates()
    {
        var stateList = new List<State>();
        var TaxesCities = new List<City>();
        TaxesCities.Add(new City(){ CityId = 1, CityName = "Dalles"});
        TaxesCities.Add(new City(){ CityId = 2, CityName = "Houstin"});
        stateList.Add(new State("TX", "Taxes" , TaxesCities));
        var NYCities = new List<City>();
        NYCities.Add(new City() { CityId = 3, CityName = "New York" });
        NYCities.Add(new City() { CityId = 4, CityName = "Brooklyn" });
        stateList.Add(new State("NY", "New York", NYCities));
        return stateList;
    }
}

2 个答案:

答案 0 :(得分:1)

问题是你正在使用CollectionViewSource,它自动选择列表中的第一个元素,因为它无法找到&#34; null&#34;的条目。就个人而言,我认为在这种情况下使用CollectionViewSource是个好主意...你已经在Person.State中跟踪当前状态了,那你为什么需要一个CollectionViewSource来保持跟踪当前项目?如果你在同一页面上有两个ComboBox,会发生什么?您需要创建另一个CollectionViewSource,以便它们不会共享相同的索引。最后,任何涉及UI的逻辑(例如,管理当前选择的项目)都应该在视图模型中完成,以便可以对其进行测试。

您的代码存在一些需要修复的问题,首先是您将第一个ComboBox的SelectedValue绑定到Person.State。没有&#34; Person&#34;主视图模型的成员,我怀疑你的意思是NewPerson,对吗?其次,Person.State字段是一个字符串,但是你的ComboBox绑定到一个状态列表,所以当用户选择一个状态时,WPF将调用该状态的ToString()成员并将其设置为值,即你的Person。状态字段最终会出现像&#34; YourProjectName.State&#34;。您可以修复绑定来执行此操作,但更好的解决方案是将Person类修改为直接引用State和City:

    private State state;
    public State State
    {
        get {return state;}
        set {state = value; OnPropertyChanged("State");}

    }

    private City city;
    public City City
    {
        get {return city;}
        set {city = value; OnPropertyChanged("City");}
    }

(请注意,您原来的城市成员存在问题......您已将其更改为CityId,但您正在On&#34; City&#34;)上进行OnPropertyChanged。

除了在性能方面要好得多之外,你还没有遇到组合框设置初始状态错误的问题,如果你修复了XAML绑定中的其他问题,你的主视图现在也能正常工作:

    <ComboBox SelectedValue="{Binding NewPerson.State}" Width="150" DisplayMemberPath="StateName" ItemsSource="{Binding States}" />
    <ComboBox SelectedValue="{Binding NewPerson.City}" DisplayMemberPath="CityName" ItemsSource="{Binding NewPerson.State.Cities}" />

如果你真的希望你的Person类使用州名和城市id,那么你应该创建一个PersonViewModel,它包含对它的引用并进行转换。这毕竟是你应该如何在MVVM中构建你的数据......人真的是一个模型对象。

答案 1 :(得分:0)

您正在将SelectedIndex初始化为-1,但随后绑定了覆盖初始选择的SelectedValue。您有3个选择:

  1. 删除SelectedIndex并将初始SelectedValue设置为不在列表中的内容。
  2. 将SelectedIndex绑定到视图模型中的整数,并在绑定建立后在运行时将其设置为-1。
  3. 保持原样,但将SelectedValue的绑定模式设置为OneWayToSource。这将阻止绑定覆盖初始值,但如果您在视图模型中进行更改,它将不会反映对SelectedIndex的任何更改。