WPF - 获取 DataGridTemplateColumn 中 Combobox 控件的行索引
WPF - get row index for Combobox control in DataGridTemplateColumn
我想知道如何做到这一点。
我有一个 DataGridTemplateColumn
,里面有一个简单的 ComboBox
控件。
该组合框有一个链接到它的 SelectionChanged
事件。
在更改的事件中,我想知道更改的行的行索引是从更改的组合框派生的。
我是不是采取了错误的方法?
这是我拥有的:
<DataGrid AutoGenerateColumns="False" Margin="5,10,5,5"
x:Name="dgrMatches" ItemsSource="{Binding .}"
CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserSortColumns="False"
SelectionMode="Single" SelectionUnit="FullRow" IsReadOnly="False"
RowStyle="{DynamicResource EditableRows}" CellStyle="{DynamicResource EditableTableCells}">
<DataGrid.Columns>
<DataGridTextColumn ... />
<DataGridTemplateColumn Header="Legs won" Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="cbbLegsWonA"
SelectedIndex="{Binding LegsWonA, Mode=TwoWay}"
ItemsSource="{Binding NumberOfLegs}"
SelectionChanged="cbbLegsWonA_SelectionChanged" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- @Chris Eelmaa -->
<DataGridTemplateColumn Header="Legs won" Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="cbbLegsWonB"
SelectedIndex="{Binding LegsWonB, Mode=TwoWay}"
ItemsSource="{Binding NumberOfLegs}"
SelectionChanged="cbbLegsWonB_SelectionChanged" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn ... />
</DataGrid.Columns>
</DataGrid>
和事件处理程序:
private void cbbLegsWonA_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox cbbLegsA = e.Source as ComboBox; // Altered combobox
int rowIndex = -1;
if (cbbLegsA.Tag == null)
{
DataGridRow row = (DataGridRow)dgrMatches.ContainerFromElement(cbbLegsA);
rowIndex = row.GetIndex();
cbbLegsA.Tag = rowIndex;
}
else
{
Int32.TryParse(cbbLegsA.Tag.ToString(), out rowIndex);
}
//@ChrisEelmaa: Basically, change the bound list and refresh the items in the datagrid
//The debugger doesn't get to this point, ofcourse
SingleMatch match = matches.ElementAt(rowIndex); // Get the current match out of the bound list
match.LegsWonA = cbbLegsA.SelectedIndex; // Manually change second combobox item
dgrMatches.Items.Refresh();
...
}
这不起作用:(DataGridRow)dgrMatches.ContainerFromElement(cbbLegsA) == null
(DataGridRow)dgrMatches.ContainerFromElement(cbbLegsA) == null
不起作用,因为特定行的 DataGrid 的 ItemContainer 不是来自您的 DataTemplate 的 ComboBox,它是一个包含 'templated' 版本的 ComboBox 的 DataGridRow
.相反,您需要使用 VisualTreeHelper.FindParent() 从 ComboBox 中查找 DataGridRow(因为您的 ComboBox 位于 DataGridRow 的可视树中,而不是逻辑树中)。您可以从 DataGridRow 参考中轻松找到行索引。然而...
评论中建议的更好的方法是使用 MVVM 模式。您的 ComboBox 将绑定到 ViewModel 中的属性。当 ViewModel 中的一个 属性 发生变化时,您可以轻松地更新另一个以实现您想要的行为,而无需在可视化树中进行任何丑陋的搜索,或者在后面留下一堆 UI 代码。不是一个 ComboBox 自动更新另一个在你的 UI 中的逻辑,它更容易控制视图的对象模型(又名 'ViewModel')它应该在的地方。
我想知道如何做到这一点。
我有一个 DataGridTemplateColumn
,里面有一个简单的 ComboBox
控件。
该组合框有一个链接到它的 SelectionChanged
事件。
在更改的事件中,我想知道更改的行的行索引是从更改的组合框派生的。
我是不是采取了错误的方法? 这是我拥有的:
<DataGrid AutoGenerateColumns="False" Margin="5,10,5,5"
x:Name="dgrMatches" ItemsSource="{Binding .}"
CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserSortColumns="False"
SelectionMode="Single" SelectionUnit="FullRow" IsReadOnly="False"
RowStyle="{DynamicResource EditableRows}" CellStyle="{DynamicResource EditableTableCells}">
<DataGrid.Columns>
<DataGridTextColumn ... />
<DataGridTemplateColumn Header="Legs won" Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="cbbLegsWonA"
SelectedIndex="{Binding LegsWonA, Mode=TwoWay}"
ItemsSource="{Binding NumberOfLegs}"
SelectionChanged="cbbLegsWonA_SelectionChanged" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- @Chris Eelmaa -->
<DataGridTemplateColumn Header="Legs won" Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="cbbLegsWonB"
SelectedIndex="{Binding LegsWonB, Mode=TwoWay}"
ItemsSource="{Binding NumberOfLegs}"
SelectionChanged="cbbLegsWonB_SelectionChanged" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn ... />
</DataGrid.Columns>
</DataGrid>
和事件处理程序:
private void cbbLegsWonA_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox cbbLegsA = e.Source as ComboBox; // Altered combobox
int rowIndex = -1;
if (cbbLegsA.Tag == null)
{
DataGridRow row = (DataGridRow)dgrMatches.ContainerFromElement(cbbLegsA);
rowIndex = row.GetIndex();
cbbLegsA.Tag = rowIndex;
}
else
{
Int32.TryParse(cbbLegsA.Tag.ToString(), out rowIndex);
}
//@ChrisEelmaa: Basically, change the bound list and refresh the items in the datagrid
//The debugger doesn't get to this point, ofcourse
SingleMatch match = matches.ElementAt(rowIndex); // Get the current match out of the bound list
match.LegsWonA = cbbLegsA.SelectedIndex; // Manually change second combobox item
dgrMatches.Items.Refresh();
...
}
这不起作用:(DataGridRow)dgrMatches.ContainerFromElement(cbbLegsA) == null
(DataGridRow)dgrMatches.ContainerFromElement(cbbLegsA) == null
不起作用,因为特定行的 DataGrid 的 ItemContainer 不是来自您的 DataTemplate 的 ComboBox,它是一个包含 'templated' 版本的 ComboBox 的 DataGridRow
.相反,您需要使用 VisualTreeHelper.FindParent() 从 ComboBox 中查找 DataGridRow(因为您的 ComboBox 位于 DataGridRow 的可视树中,而不是逻辑树中)。您可以从 DataGridRow 参考中轻松找到行索引。然而...
评论中建议的更好的方法是使用 MVVM 模式。您的 ComboBox 将绑定到 ViewModel 中的属性。当 ViewModel 中的一个 属性 发生变化时,您可以轻松地更新另一个以实现您想要的行为,而无需在可视化树中进行任何丑陋的搜索,或者在后面留下一堆 UI 代码。不是一个 ComboBox 自动更新另一个在你的 UI 中的逻辑,它更容易控制视图的对象模型(又名 'ViewModel')它应该在的地方。