c# - 如何在 ItemsControl 中等待容器的生成?
问题描述
我有一个SettingsWindow
,其中有一个音频文件选择器,它有一个上下文菜单。一些代码MyAudioFileSelector
在获得之前访问计算属性,AudioFileSelector
因为AudioFileSelector
它只是在当时尚未生成其容器DataTemplate
的项的a 内。ItemsControl
我试图推迟MyAudioFileSelector
使用Dispatcher.BeginInvoke
with的访问DispatcherPrority.Loaded
,但此时项目容器仍未生成。
访问 的代码MyAudioFileSelector
是应用用户选择的数据文件中的许多设置之一的方法。对于程序的数据文件模式中的每个设置,此方法从Window
的事件处理程序中同步调用。Loaded
我对 async-await 编程很陌生,我读过这个,但我不确定这对我有什么帮助,我读了这个页面,但我仍然不知道该怎么做。我已阅读此内容,但唯一未被接受的答案似乎与我在下面已经使用的类似:
MySettingsWindow.Dispatcher.BeginInvoke(new Action(() =>
{
[...]
}), System.Windows.Threading.DispatcherPriority.Loaded);
XAML 的一部分
(InverseBooleanConv
只做true
, false
, 和false
, true
)
<ItemsControl Grid.ColumnSpan="3" Margin="0,0,-0.6,0" Grid.Row="0"
ItemsSource="{Binding SettingsVMs}" x:Name="MyItemsControl">
<ItemsControl.Resources>
<xceed:InverseBoolConverter x:Key="InverseBooleanConv"/>
<DataTemplate DataType="{x:Type local:AudioFileSettingDataVM}">
<local:AudioFileSelector MaxHeight="25" Margin="10" FilePath="{Binding EditedValue, Mode=TwoWay}">
<local:AudioFileSelector.RecentAudioFilesContextMenu>
<local:RecentAudioFilesContextMenu
PathValidationRequested="RecentAudioFilesContextMenu_PathValidationRequested"
StoragePropertyName="RecentAudioFilePaths"
EmptyLabel="No recent audio files."/>
</local:AudioFileSelector.RecentAudioFilesContextMenu>
</local:AudioFileSelector>
</DataTemplate>
[...]
部分代码隐藏
在 MainWindow.xaml.cs 中,Window_Loaded
处理程序的开头
private void Window_Loaded(object sender, RoutedEventArgs e)
{
VM.ClockVMCollection.Model.FiltersVM.Init();
VM.Settings.IsUnsavedLocked = true;
VM.ClockVMCollection.Model.IsUnsavedLocked = true;
foreach (KeyValuePair<string, SettingDataM> k in VM.Settings)
{
ApplySetting(k.Value);
}
[...]
在 MainWindow.xaml.cs 的方法中ApplySetting
case "AlwaysMute":
VM.MultiAudioPlayer.Mute = (bool)VM.Settings.GetValue("AlwaysMute");
break;
case "RecentAudioFilePaths":
MySettingsWindow.Dispatcher.BeginInvoke(new Action(() =>
{
MySettingsWindow.MyRecentAudioFilesContextMenu. // here, MyRecentAudioFilesContextMenu is null, this is the problem
LoadRecentPathsFromString(VM.Settings.GetValue("RecentAudioFilePaths") as string);
}), System.Windows.Threading.DispatcherPriority.Loaded);
break;
case "RecentImageFilePaths":
MySettingsWindow.Dispatcher.BeginInvoke(new Action(() =>
{
MySettingsWindow.MyRecentImageFilesContextMenu. // here, MyRecentImageFilesContextMenu is null, this is the problem
LoadRecentPathsFromString(
VM.Settings.GetValue("RecentImageFilePaths") as string);
}), System.Windows.Threading.DispatcherPriority.Loaded);
break;
[...]
在SettingsWindow
课堂上
internal AudioFileSelector MyAudioFileSelector
{
get
{
foreach (SettingDataVM vm in MyItemsControl.ItemsSource)
{
if (vm is AudioFileSettingDataVM)
{
return (AudioFileSelector)MyItemsControl.ItemContainerGenerator.ContainerFromItem(vm);
}
}
return null;
}
}
internal ImageFileSelector MyImageFileSelector
{
get
{
foreach (SettingDataVM vm in MyItemsControl.ItemsSource)
{
if (vm is ImageFileSettingDataVM)
{
return (ImageFileSelector)MyItemsControl.ItemContainerGenerator.ContainerFromItem(vm);
}
}
return null;
}
}
internal RecentAudioFilesContextMenu MyRecentAudioFilesContextMenu
{
get
{
return MyAudioFileSelector?.RecentAudioFilesContextMenu;
}
}
internal RecentFilesContextMenu MyRecentImageFilesContextMenu
{
get
{
return MyImageFileSelector?.RecentImageFilesContextMenu;
}
}
该错误位于上述代码片段之一中的两个 C# 注释中,即空引用异常。
我想我可以在MainWindow
a 处理程序中附加到SettingsWindow
's ItemsControl
'ItemContainerGenerator
事件StatusChanged
,然后继续初始化窗口,包括加载所有设置,但我想知道是否有更有序/正确的方法。
谢谢你。
解决方案
ItemsControl
如果您可以在变量 name 下的代码隐藏中访问您的MyItemsControl
,那么您可以为事件添加事件处理程序ContainerGenerator
StatusChanged
:
private void Window_Loaded(object sender, RoutedEventArgs e) {
//Subscribe to generated containers event of the ItemsControl
MyItemsControl.ItemContainerGenerator.StatusChanged += ContainerGenerator_StatusChanged;
}
/// <summary>
/// Handles changed in container generator status.
///</summary>
private void ContainerGenerator_StatusChanged(object sender, EventArgs e) {
var generator = sender as ItemContainerGenerator;
//Check that containers have been generated
if (generator.Status == GeneratorStatus.ContainersGenerated ) {
//Do stuff
}
}
如果您只是从文件中保存/加载数据,我真的建议不要使用它,因为它们完全不相关。
推荐阅读
- microsoft-graph-api - Microsoft Graph:无法使用可嵌入 iframe 的 URL
- javascript - 如何在一行上将字符串偶数索引和奇数索引字符打印为 2 个空格分隔的字符串?
- php - 将分类详细信息添加到自定义帖子类型 - 以显示 SEO 详细信息
- python - ctypes.Structure.from_buffer_copy 不检查 \0 的 c_char-type
- google-apps-script - 在 Google 表格中上下移动行的快捷方式
- azure - 如何使用 PowerShell 创建启用分析存储的 Cosmos DB Sql 容器?
- spring - spring-boot 2.3.7 spring-boot-starter-integration CVE-2019-3772
- networking - 如何以一个字符串的形式阻止 155.155.64.0 - 155.155.127.255 这样的范围?
- redactor - 无法读取 Redactor 中未定义的属性“替换”
- java - 如何在 oracle 中将 dto 数据保存为 json 并使用 java/hibernate 将其读回