WinUI3中如何获取ItemsRepeater内UI元素的上下文?
WinUI3 ItemsRepeater子元素DataContext为空问题解决
问题场景
我使用WinUI3和C#开发应用,通过ItemsRepeater搭配DataTemplate动态渲染快捷键设置面板,渲染功能正常,但需要获取每个ComboBox所属的原KeyboardShortcut列表项来设置默认值时,发现ItemsRepeater内所有子元素的DataContext均为空,无法关联到对应的列表项。
现有代码
XAML代码
<Grid> <StackPanel Orientation="Vertical"> <ItemsRepeater ItemsSource="{x:Bind _keyboardShortcuts}"> <ItemsRepeater.ItemTemplate> <DataTemplate x:DataType="dmgmt:KeyboardShortcut"> <Border x:Name="bdrKeyboardShortcutBorder" Background="{ThemeResource SystemChromeMediumHighColor}" CornerRadius="10" Margin="10"> <Grid Margin="10" HorizontalAlignment="Stretch"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="Execute Code" VerticalAlignment="Center"/> <StackPanel Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Orientation="Horizontal"> <ComboBox Width="150" Margin="10,0,10,0" ItemsSource="{x:Bind Path=dmgmt:KeyboardShortcut.AvailableVirtualKeyModifiers}" SelectionChanged="ComboBoxModifier_SelectionChanged" Loaded="ComboBoxModifier_Loaded"/> <ComboBox Width="150" Margin="10,0,10,0" ItemsSource="{x:Bind Path=dmgmt:KeyboardShortcut.AvailableVirtualKeyCodes}" SelectionChanged="ComboBoxKey_SelectionChanged" Loaded="ComboBoxKey_Loaded"/> </StackPanel> </Grid> </Border> </DataTemplate> </ItemsRepeater.ItemTemplate> </ItemsRepeater> </StackPanel> </Grid>
C#列表定义
private List<KeyboardShortcut> _keyboardShortcuts { get; set; } = new() { PyruxSettings.Keybinds.StartShortcut, PyruxSettings.Keybinds.StepShortcut, PyruxSettings.Keybinds.ResetShortcut, PyruxSettings.Keybinds.PeakGoalLayoutShortcut, PyruxSettings.Keybinds.SaveShortcut };
解决方法
WinUI3中x:Bind默认是编译时绑定,不会自动设置DataContext,这是导致DataContext为空的核心原因,可通过以下两种方式解决:
方式1:显式设置DataTemplate根元素的DataContext
修改DataTemplate的根Border,添加DataContext="{x:Bind}",让模板内所有元素继承对应的KeyboardShortcut实例:
<DataTemplate x:DataType="dmgmt:KeyboardShortcut"> <Border x:Name="bdrKeyboardShortcutBorder" DataContext="{x:Bind}" Background="{ThemeResource SystemChromeMediumHighColor}" CornerRadius="10" Margin="10"> <!-- 原有内容保持不变 --> </Border> </DataTemplate>
之后在ComboBoxModifier_Loaded或SelectionChanged事件中,即可通过((ComboBox)sender).DataContext获取到对应的KeyboardShortcut对象,进而设置默认选中项。
方式2:直接用x:Bind绑定选中项(推荐)
利用x:Bind直接将ComboBox的SelectedItem绑定到KeyboardShortcut的对应属性,无需手动处理事件,更符合数据驱动逻辑:
假设KeyboardShortcut类包含SelectedModifier和SelectedKey属性,修改ComboBox的XAML代码:
<ComboBox Width="150" Margin="10,0,10,0" ItemsSource="{x:Bind Path=dmgmt:KeyboardShortcut.AvailableVirtualKeyModifiers}" SelectedItem="{x:Bind SelectedModifier, Mode=TwoWay}"/> <ComboBox Width="150" Margin="10,0,10,0" ItemsSource="{x:Bind Path=dmgmt:KeyboardShortcut.AvailableVirtualKeyCodes}" SelectedItem="{x:Bind SelectedKey, Mode=TwoWay}"/>
这样ComboBox会自动根据KeyboardShortcut的属性值设置默认选中项,修改后的选中值也会同步回原对象。
补充说明
x:Bind默认是OneTime模式,若需要双向同步选中值到数据源,需显式指定Mode=TwoWay。- 若
KeyboardShortcut类需要支持属性变更通知,需实现INotifyPropertyChanged接口,否则UI不会自动响应属性变化。
内容的提问来源于stack exchange,提问作者LightJack05
相关产品推荐
相关产品推荐

