以下是这种情况:我有一个对象列表,每个对象都带有一个ID号。我正在尝试根据对象的ID号在listview的列中设置一个值:
<ListView Name="Listview1"
Itemsource="{Binding ObjectList}">
<ListView.View>
<GridView>
<GridViewColumn Header="Header1" DisplayMemberBinding="{Binding subObject.property}"/>
<GridViewColumn Header="Header2" DisplayMemberBinding="{Binding PropertyOfAnItemInAList"/>
</GridView>
</ListView.View>
</ListView>
ObjectList是ViewModel中的一个属性,它向ListView证明了一个ObservableCollection进行处理。 Header1和Header2绑定到ObservableCollection中名为“ObjectList”的项目中的属性。
这一切都适用于Header1。问题是Header2需要从驻留在ObservableCollection的每个元素内的列表中选择一个项目,并根据ObjectList中引用项目的另一个属性显示它。
那我该怎么做?
我设法通过在ObjectList中的对象内部设置一个名为“currentSelection”的变量来设置它,然后当绑定从ItemSource迭代ObjectList以生成ListView时,它就会被设置:
public ObservableCollection<theObject> ObjectList {
get {
foreach (theObject obj in sourceCollection) {
obj.CurrentID = MyID;
}
return new ObservableCollection<theObject>sourceCollection // <-- secondary question: Is this the best way to send an observableCollection to a View???
}
}
然而,这感觉有点像黑客而不是最佳实践,那么还有另一种更好的方法来完成同样的事情吗?
编辑:
这是ObjectList中对象的片段,就像我现在所拥有的那样。
public class ObjectInObjectList {
/* constructor and various properties snipped to save space */
private subObject subObj;
public int CurrentID {get; set;}
public SubObject {
get { return subObject; } // etc...
}
private SortedList<int,int> valuesIWantInSecondColumn
Public int PropertyOfAnItemInAList {
return valuesIWantInSecondColumn[currentID];
}
答案 0 :(得分:2)
我会从对象中删除CurrentID属性。我不想在我的域对象中拥有UI属性。我认为最好的解决方案是为该列使用多重绑定,并从ViewModel为其提供SortedList和MyID值,使用转换器从sortedlist返回所选项。这样的事情(假设列出的组合框也是如此):
<ComboBox Grid.Column="0" ItemsSource="{Binding Ids}" SelectedItem="{Binding MyID}" />
<ListView Name="Listview1" Grid.Column="1" ItemsSource="{Binding ObjectList}">
<ListView.View>
<GridView>
<GridViewColumn Header="Header1" DisplayMemberBinding="{Binding subObject.property}"/>
<GridViewColumn Header="Header2" >
<GridViewColumn.DisplayMemberBinding>
<MultiBinding Converter="{StaticResource IDictionarySelector}">
<Binding Path="PropertyOfAnItemInAList" />
<Binding Path="DataContext.MyID" RelativeSource="{RelativeSource AncestorType={x:Type Window}}" />
</MultiBinding>
</GridViewColumn.DisplayMemberBinding>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
我测试了这段代码并且必须将toString()调用添加到return,否则它给了我一个绑定错误,textblock需要一个字符串值(感谢Snoop):
public class IDictionarySelector : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values != null && values.Length == 2)
{
IDictionary idictionary = values[0] as IDictionary;
int? key = values[1] as int?;
if ((idictionary != null) && (key != null) && (idictionary.Contains(key)))
{
return idictionary[key].ToString();
}
}
return null;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
答案 1 :(得分:0)
您只需要在ObjectInObjectList
课程的属性上实施INotifyPropertyChanged
Interface即可。特别是,当PropertyOfAnItemInAList
属性发生更改时,您需要告诉接口CurrentID
属性已更改:
public int CurrentID
{
get { return currentID; }
set
{
currentID = value;
NotifyPropertyChanged("CurrentID");
NotifyPropertyChanged("PropertyOfAnItemInAList");
}
}
每次PropertyOfAnItemInAList
属性更改时,此通知都会更新用户界面中的CurrentID
属性,因此您不需要任何特殊类型的Binding
。