WPF嵌套DataGrid:如何获取InnerGrid的SelectedItem?
解决嵌套DataGrid中InnerGrid SelectedItem绑定失效的问题(Caliburn.Micro环境)
我之前也碰到过一模一样的问题,核心原因大多是绑定上下文不对或者属性变更通知没做好,结合你用Caliburn.Micro的情况,给你几个可行的解决方案:
方案1:修正绑定路径(当SelectedInner是根ViewModel的属性时)
你的InnerGrid默认的DataContext是外层DataGrid的单条行数据(也就是OuterGrid集合里的某个对象),如果SelectedInner是定义在根ViewModel里的,直接写{Binding SelectedInner}肯定找不到这个属性,得通过RelativeSource指定上下文:
<DataGrid ItemsSource="{Binding InnerGrid}" SelectedItem="{Binding DataContext.SelectedInner, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" SelectionMode="Single"> <!-- 列定义 --> </DataGrid>
这里通过RelativeSource找到外层的DataGrid,它的DataContext就是你的根ViewModel,这样就能正确绑定到根级别的SelectedInner属性了。
方案2:把SelectedInner放到外层行对象中(更贴合MVVM的拆分)
如果业务上每个外层行对应的InnerGrid选中项应该属于该行数据,那可以把SelectedInner定义在外层行的模型类里,同时要确保这个模型继承Caliburn.Micro的PropertyChangedBase,这样属性变更才能通知UI:
外层行模型类
public class OuterGridItem : PropertyChangedBase { // 内层集合 public IEnumerable<InnerGridItem> InnerGrid { get; set; } private InnerGridItem _selectedInner; public InnerGridItem SelectedInner { get => _selectedInner; // 用Caliburn的Set方法自动触发PropertyChanged set => Set(ref _selectedInner, value); } }
这种情况下你原来的绑定代码SelectedItem="{Binding SelectedInner}"就是正确的,只要模型类正确实现了属性变更通知,选中后SelectedInner就会被赋值。
方案3:用Caliburn.Micro的消息机制直接处理事件
如果不想纠结绑定路径,也可以用Caliburn的Message.Attach来绑定InnerGrid的SelectionChanged事件,直接在ViewModel里拿到选中项:
XAML代码
<DataGrid ItemsSource="{Binding InnerGrid}" cal:Message.Attach="[Event SelectionChanged] = [Action HandleInnerSelectionChanged($eventArgs)]"> <!-- 列定义 --> </DataGrid>
根ViewModel里的处理方法
public class MainViewModel : Screen { private InnerGridItem _selectedInner; public InnerGridItem SelectedInner { get => _selectedInner; set => Set(ref _selectedInner, value); } public void HandleInnerSelectionChanged(SelectionChangedEventArgs e) { // 取第一个选中的项(如果是单选模式) if (e.AddedItems.Count > 0) { SelectedInner = e.AddedItems[0] as InnerGridItem; } } }
额外注意点
- 确保InnerGrid的
SelectionMode设置为Single(默认就是),如果是Extended或Multiple,SelectedItem只会返回第一个选中项,或者你需要用SelectedItems集合。 - 根ViewModel要继承Caliburn的
Screen或PropertyChangedBase,确保属性变更能通知UI。
内容的提问来源于stack exchange,提问作者gnjago
相关产品推荐
相关产品推荐

