我没有找到解决方案,但我认为它应该是可行的。
我在一个集合中有很多项目,想要选择其中的一些。每个项目都有一个CanInclude属性,包含可以选择的元素(如果已经选中)。
在其他地方选择了一个起始元素。
因此,如果开始项目是Item1,我想要一个包含Item4和Item5的组合框。如果我在这个组合框中选择Item5并单击一个'+'按钮我想在下面找到一个新的Box,其中包含Item2,Item3(从最后一个复选框)和Item4(从开始项目开始),依此类推,直到没有其他项目可以选择或用户点击“确定”。
我想到了viewmodel中的一个简单集合,其中[0]包含start元素,[1]是1. comboBox的选定元素,依此类推。但我不知道我应该如何动态添加组合框或让comboBox在所选项的集合中创建[n]元素。此外,我想不出一种方法可以在新复选框中包含已选择项目的CanInclude属性的所有项目。
如果有人有想法,我会非常感激。
修改 只是为了表达我想要像这样(包括伪代码,因为你不能做{Binding} + {Binding},但我认为你明白了):
<ComboBox ItemsSource="{Binding Path=SelectableItems}" SelectedItem="{Binding Path=SelectedItem1}" />
<ComboBox ItemsSource="{Binding Path=SelectedItem1.CanInclude}" SelectedItem="{Binding Path=SelectedItem2}"/>
<ComboBox ItemsSource="{Binding Path=SelectedItem1.CanInclude} + {Binding Path=SelectedItem2.CanInclude} - {Binding Path=SelectedItem1} - {Binding Path=SelectedItem2}" SelectedItem="{Binding Path=SelectedItem3}"/>
但我希望它适用于非固定数量的条目。
答案 0 :(得分:1)
您可以模板化ListBox,以便每个项目都是一个组合框。这样,您可以将ListBox的数据源绑定到表示项目的ViewModel的ObservableCollection。类似的东西:
public class TopLevelViewModel
{
private List<ItemViewModel> _allItems;
public ObservableCollection<ItemViewModel> CurrentlySelectedItems { get; set; }
public TopLevelViewModel()
{
DefineAllItems()
SelectFirstItem()
}
private void DefineAllItems()
{
ItemViewModel item1 = new ItemViewModel { Name = "Item1" }
item1.SelectedItemChanged += HandleItemViewModelSelectedItemChanged;
ItemViewModel item2 = new ItemViewModel { Name = "Item2" }
item2.SelectedItemChanged += HandleItemViewModelSelectedItemChanged;
ItemViewModel item3 = new ItemViewModel { Name = "Item3" }
item3.SelectedItemChanged += HandleItemViewModelSelectedItemChanged;
item1.CanInclude = new ObservableCollection<ItemViewModel>
{
item2, item3
}
item2.CanInclude = new ObservableCollection<ItemViewModel>
{
item3
}
_allItems = new List<ItemViewModel>
{
item1, item2, item3
}
}
private void SelectFirstItem()
{
//Add item1 as the first combobox
CurrentlySelectedItems.Add(_allItems[0]);
}
private void HandleItemViewModelSelectedItemChanged(object sender, EventArgs e)
{
ItemViewModel parent = (ItemViewModel)sender;
//Find the view model whose item has changed in the CurrentlySelectedItems
int indexOfParent = CurrentlySelectedItems.IndexOf(parent);
//Remove all itemviewmodels below that item
CurrentlySelectedItems.RemoveRange(
indexOfParent+1,
CurrentlySelectedItems.Count-(indexofParent+1))
//Add the selected item into the list
CurrentlySelectedItems.Add(parent.SelectedItem);
}
}
public class ItemViewModel
{
public string Name { get; set; }
public ObservableCollection<ItemViewModel> CanInclude { get; set; }
public ItemViewModel SelectedItem { get; set; }
public event EventHandler SelectedItemChanged;
}
然后将ListBox绑定到CurrentlySelectedItems,将模板内的ComboBox绑定到CanInclude:
<ListBox ItemsSource="{Binding CurrentlySelectedItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding CanInclude}"
DisplayMemberPath="{Binding Title}"
SelectedItem="{Binding SelectedItem}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
编辑添加更适合问题的解决方案:
的Xaml:
<ListBox ItemsSource="{Binding PreviouslySelectedItems}"/>
<ComboBox ItemsSource="{Binding CanInclude}"
DisplayMemberPath="{Binding Title}"
SelectedItem="{Binding SelectedItem}"/>
<Button Content="Add"
Command="{Binding AddCommand}"/>
视图模型:
public class TopLevelViewModel
{
public ObservableCollection<ItemViewModel> PreviouslySelectedItems { get; private set; }
public ObservableCollection<ItemViewModel> CanInclude { get; private set; }
public ItemViewModel SelectedItem { get; set; }
//Set up all the items as above, and pre-populate the first item
//and the initial CanInclude options.
//When the Add button is clicked
public void ExecuteAdd()
{
//Add the currently selected item to the Listbox
PreviouslySelectedItems.Add(SelectedItem)
//Rebuild the CanInclude list
CanInclude.Clear();
var newCanInclude =
PreviouslySelectedItems.SelectMany(x => x.CanInclude)
.Where(x => !PreviouslySelectedItems.Contains(x))
CanInclude.AddRange(newCanInclude);
}
}