在我的C#/ WPF / .NET 4.5项目中,我有一个ObservableCollection<int>
来保存索引。我还有一个ListBox
,其ItemsPanelTemplate
设置为UniformGrid
(包含20行和20列),其ItemTemplate
设置为CheckBox
es。< / p>
我希望ObservableCollection<int>
保存已检查的CheckBoxes
的索引。这应该通过TwoWay
绑定来完成:当int
添加ObservableCollection
时,CheckBoxes
UniformGrid
中的CheckBox
应该被选中或取消选中;当我选中或取消选中ObservableCollection
时,应将其索引添加到<ListBox
x:Name="myListBox"
SelectionMode="Multiple"
ItemsSource="{Binding Cells, Converter={StaticResource cellsConverter}}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="20" Columns="20"></UniformGrid>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
或从ObservableCollection<int>
中删除。
我尝试使用转换器以下列方式完成此操作:
XAML:
public class Frame : INotifyPropertyChanged {
private ObservableCollection<int> _cells;
public ObservableCollection<int> Cells {
get { return _cells; }
set {
_cells = value;
OnPropertyChanged("Cells");
}
}
public Frame() {
Cells = new ObservableCollection<int>();
}
// Event handler for INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
包含[ValueConversion(typeof(ObservableCollection<int>), typeof(ObservableCollection<bool>))]
public class CellsConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
ObservableCollection<int> ints = (ObservableCollection<int>)value;
ObservableCollection<bool> bools = new ObservableCollection<bool> ();
for (int i = 0; i < 400; i++) {
bool b = new bool();
if (ints.Contains(i)) b = true;
else b = false;
bools.Add(b);
}
return bools;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
ObservableCollection<bool> bools = (ObservableCollection<bool>)value;
ObservableCollection<int> ints = new ObservableCollection<int>();
foreach (bool b in bools) {
if (b == true) ints.Add(bools.IndexOf(b));
}
return ints;
}
}
的类
XamlParseException
转换器:
ListBox
这可能不是实现此目的的理想方法,在这种情况下,如果有人提出不同的方法,我将不胜感激。
当我运行它时,我得到一个ParentOfMyListBox.DataContext = new Frame();
说“双向绑定需要Path或XPath”。我想问题类似于the one posted here,但我无法弄清楚如何将解决方案应用到我使用转换器的情况。
问题:
indexes.Add(0);
indexes.Add(3);
的好方法吗?修改
为清楚起见,说明了我想要实现的目标:
indexes.Remove(0);
myListBox的外观:
indexes
3
然后,如果我手动检查其中一个单元格......
现在8
包含{{1}}和{{1}}。
答案 0 :(得分:3)
记住,亲吻 - 保持简单,愚蠢。
1)创建一个包装类,其中包含:
在XAML中,绑定IsChecked属性:
<ListBox
SelectionMode="Multiple"
ItemsSource="{Binding Cells}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="20" Columns="20"></UniformGrid>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
现在,如果你需要获得ObservableCollection;你可以使用简单的LINQ查询:
new ObservableCollection<int>(Cells.Where(x= x.IsChecked).Select(x => x.Value));
转换器破解不应该使用,但可以给你实现它的想法没有一个:
private void UpdateUnderlyingCollection(
ObservableCollection<int> underlyingCollection ,
int element,
bool isChecked)
{
if (!isChecked)
underlyingCollection.Remove(element);
else if(!underlyingCollection.Contains(element))
underlyingCollection.Add(element);
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// todo; weak references
var underlyingCollection = (ObservableCollection<int>)value;
var lookup = underlyingCollection.ToLookup(x => x);
var presentableCollection = new ObservableCollection<Wrap>();
foreach (var i in Enumerable.Range(0, 400))
{
var damnLambdaYuNoCaptureByValue = i;
var wrap = new Wrap { IsChecked = lookup.Contains(i)};
wrap.PropertyChanged += (sender, args) =>
{
if(args.PropertyName == "IsChecked")
UpdateUnderlyingCollection(
underlyingCollection,
damnLambdaYuNoCaptureByValue,
wrap.IsChecked);
};
presentableCollection.Add(wrap);
}
return presentableCollection;
}