问题描述
我有一个绑定到 CollectionViewSource 的 ComboBox,我希望默认情况下所选索引应为 -1(因为不应选择任何内容)我已设置 SelectedIndex="-1"并且第一项仍然被选中.为什么?
I've a ComboBox Bound To a CollectionViewSource and I want that by default the selected index should be -1 (Because nothing should be selected) I've set SelectedIndex="-1"and the first item is still selected. Why?
我的视图 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#
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;
}
}
推荐答案
问题是您使用的 CollectionViewSource 会自动选择列表中的第一个元素,因为它找不到null"的条目.我个人认为在这种情况下使用 CollectionViewSource 不是一个好主意……您已经在 Person.State 中跟踪当前状态,那么为什么还需要 CollectionViewSource 来跟踪当前项目?如果在同一页面上有两个 ComboBox 会发生什么?您需要创建另一个 CollectionViewSource 以便它们不会共享相同的索引.最后,任何涉及 UI 的逻辑(例如管理当前选定的项目)都应该在视图模型中完成,以便可以对其进行测试.
The problem is you're using a CollectionViewSource which is automatically selecting the first element in the list because it can't find an entry for "null". Personally I don't think it's a good idea to use a CollectionViewSource in this case...you're already keeping track of the current state in Person.State so why do you need a CollectionViewSource to keep track of the current item as well? Also what happens if you have two ComboBox's on the same page? You'll need to create another CollectionViewSource so that they don't both share the same index. And finally any logic involving the UI (e.g. managing a currently selected item) should be done in the view model so that it can be tested.
您的代码有一些问题需要修复,首先是您将第一个 ComboBox 的 SelectedValue 绑定到 Person.State.主视图模型中没有Person"成员,我怀疑您的意思是 NewPerson,对吗?其次,Person.State 字段是一个字符串,但您的 ComboBox 绑定到一个状态列表,因此当用户选择一个状态时,WPF 将调用该状态的 ToString() 成员并将其设置为值,即您的 Person.State 字段将缠绕加上YourProjectName.State"之类的东西.您可以修复您的绑定以执行此操作,但更好的解决方案是修改您的 Person 类以直接引用 State 和 City:
There are a few problems with your code that need fixing, the first is the fact that you're binding yoru first ComboBox's SelectedValue to Person.State. There is no "Person" member of the main view model, I suspect you meant NewPerson, correct? Secondly the Person.State field is a string but your ComboBox is binding to a list of States, so when the user selects a state WPF will call that state's ToString() member and set that at the value i.e. your Person.State field will wind up with something like "YourProjectName.State". You can fix your binding to do this, but a better solution is to modify your Person class to reference State and City directly:
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");}
}
(请注意,您原来的 City 成员存在问题……您已将其更改为 CityId,但您正在对City"执行 OnPropertyChanged).
(Note there was a problem in your original City member...you'd changed it to CityId but you were doing OnPropertyChanged on "City").
除了更好的性能之外,组合框不会错误地设置初始状态,如果您修复 XAML 绑定中的其他问题,您的主视图现在也将正常工作:
Apart from being much better performance-wise you won't have problems with the combobox setting the intial state incorrectly, and if you fix up the other problems in your XAML bindings your master-view will now work properly as well:
<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 中构建数据...Person 实际上是一个模型对象.
If you really do want your Person class to use the state name and city id then you should create a PersonViewModel that holds a reference to it and does the conversion. This is, after-all, how you should be structuring your data in MVVM...Person is really a model object.
这篇关于组合框选定索引 -1 绑定到集合视图源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!