WPF中如何获取被点击的ObservableCollection元素的索引?
问题解决步骤
1. 修复ViewModel的属性递归错误
你的Numbers属性get访问器存在递归调用问题,会导致栈溢出,需改为返回私有字段:
private ObservableCollection<int> numbers = new ObservableCollection<int>() { 10, 10, 10, 10, 10, 10 }; public ObservableCollection<int> Numbers { get => numbers; // 返回私有字段numbers,而非属性本身 set { if (value != numbers) { numbers = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Numbers))); } } }
2. 修正XAML按钮绑定语法
自定义按钮的Nums依赖属性需要明确指定,修正后的XAML:
<UniformGrid x:Name="Nums" Grid.Row="1" Rows="1"> <local:Nums Nums="{Binding Numbers[0]}" Stroke="Red" Click="Button_Clicked" /> <local:Nums Nums="{Binding Numbers[1]}" Stroke="Red" Click="Button_Clicked" /> <local:Nums Nums="{Binding Numbers[2]}" Stroke="Red" Click="Button_Clicked" /> <local:Nums Nums="{Binding Numbers[3]}" Stroke="Red" Click="Button_Clicked" /> <local:Nums Nums="{Binding Numbers[4]}" Stroke="Red" Click="Button_Clicked" /> <local:Nums Nums="{Binding Numbers[5]}" Stroke="Red" Click="Button_Clicked" /> </UniformGrid>
3. 实现点击事件的数值修改逻辑
通过UniformGrid的Children集合获取点击按钮的索引,然后修改对应位置的数值:
private void Button_Clicked(object sender, RoutedEventArgs e) { var clickedBtn = sender as Nums; if (clickedBtn == null) return; // 获取按钮在集合中的索引 int index = Nums.Children.IndexOf(clickedBtn); // 仅处理非末尾按钮(末尾按钮无右侧元素) if (index < numberChangerViewModel.Numbers.Count - 1) { numberChangerViewModel.Numbers[index] -= 1; numberChangerViewModel.Numbers[index + 1] += 1; } }
4. 确保UI实时更新
ObservableCollection仅在元素增删时触发更新,修改值不会自动通知UI,需将int替换为实现INotifyPropertyChanged的自定义类:
public class NumberItem : INotifyPropertyChanged { private int _value; public int Value { get => _value; set { if (_value != value) { _value = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value))); } } } public event PropertyChangedEventHandler PropertyChanged; }
更新ViewModel的集合类型:
private ObservableCollection<NumberItem> numbers = new ObservableCollection<NumberItem>() { new NumberItem { Value = 10 }, new NumberItem { Value = 10 }, new NumberItem { Value = 10 }, new NumberItem { Value = 10 }, new NumberItem { Value = 10 }, new NumberItem { Value = 10 } }; public ObservableCollection<NumberItem> Numbers { get => numbers; set { if (value != numbers) { numbers = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Numbers))); } } }
最后修改XAML绑定路径:
<local:Nums Nums="{Binding Numbers[0].Value}" Stroke="Red" Click="Button_Clicked" /> <!-- 其余按钮同理,将Numbers[index]改为Numbers[index].Value -->
内容的提问来源于stack exchange,提问作者Jeredriq Demas
相关产品推荐
相关产品推荐

