程序在app.xaml中用ResourceDictionary来支持多语言界面显示,控件用DynamicResource方式定位语言文件中相应的内容。默认英语,用户登录成功后根据身份打开对应的功能窗口操作没有问题,但是切换到土耳其语后,在打开功能窗口时,InitializeComponent()方法报错,我用F11跟踪,还不清楚是到哪一步和哪个对象的错误。
我的疑问是:
1 有什么办法能定位到空对象?或者能知道在第几行代码出错?有没有比较好的辅助工具来调试程序?
2 wpf在切换显示语言的时候,通常会发生什么意外?
3 InitializeComponent()中程序做了一些什么是否能知道?能不能很详细的看到它一步一步执行了什么代码?
谢谢啦
我的疑问是:
1 有什么办法能定位到空对象?或者能知道在第几行代码出错?有没有比较好的辅助工具来调试程序?
2 wpf在切换显示语言的时候,通常会发生什么意外?
3 InitializeComponent()中程序做了一些什么是否能知道?能不能很详细的看到它一步一步执行了什么代码?
谢谢啦
是来构造界面的 ,可能是某个对象未实例化 ,猜测而已
我再补充一下,刚才我去掉了语言文件中的内容,显示了空对象的名称。我感到很奇怪,InitializeComponent为什么会去调用cs文件中的方法,比如,cs中我创建了一个方法,往控件ComboBox中添加item,叫AddItem()。执行的先后顺序是InitializeComponent();AddItem();按照道理,界面上应该先会生成一个ComboBox,等InitializeComponent全部完成后,再执行AddItem()方法,但是InitializeComponent的时候就会去添加item,显然,这个时候还没有ComboBox。谁能详细的解释一下InitializeComponent会发生这种情况的原因?谢谢
这个文件是解析xaml的
至于如何调试xaml,只能看堆栈信息了。。或者打印出Exception的detail.
this.Loaded += new RoutedEventHandler(Window1_Loaded);在Window1_Loaded添加AddItem的方法
这是不对的,InitializeComponent只是把控件的位置大小等确定了只有在调用Render后才会在界面上呈现。
你可以重载Window的protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
}方法,这是绘制Window时调用的
至于我前面提到的Loaded,则是比OnRender还要之后的。
public 构造函数
{
this.loaded += new RoutedEventHandler(window_load);
InitializeComponent();
}
private void window_load(object sender, RoutedEventArgs e)
{
AddItem();
}
如上所示,是这样吗?执行到InitializeComponent还是报错。
<ComboBox Name="PerPage" VerticalAlignment="Top" Width="50" SelectionChanged="PerPage_SelectionChanged" SelectedValuePath="Tag">
<ComboBoxItem Content="5" Tag="5"/>
<ComboBoxItem Content="10" Selector.IsSelected="True" Tag="10" />
<ComboBoxItem Content="15" Tag="15"/>
<ComboBoxItem Content="All"/>
</ComboBox>
以上是xaml中的代码。InitializeComponent()的时候,会调用PerPage_SelectionChanged(),不知道是不是在生成combobox的时候,在添加ComboBoxItem时触发了PerPage_SelectionChanged()。因为一共有4个这样的combobox,前2个执行通过,在第2个结束的时候,就直接报对象空错误。
因为有2个语言切换,英文没有报错,切换到其他语言才显示错误,所以我在想是不是因为其他语言造成的,但是又无法了解具体的原因。
以下是详细错误信息:
System.NullReferenceException occurred
Message=Object reference not set to an instance of an object.
Source=mscorlib
StackTrace:
at System.DefaultBinder.BindToMethod(BindingFlags bindingAttr, MethodBase[] match, Object[]& args, ParameterModifier[] modifiers, CultureInfo cultureInfo, String[] names, Object& state)
at MS.Internal.Xaml.Runtime.DynamicMethodRuntime.CreateInstanceWithCtor(Type type, Object[] args)
at MS.Internal.Xaml.Runtime.DynamicMethodRuntime.CreateInstanceWithCtor(XamlType xamlType, Object[] args)
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstance(XamlType xamlType, Object[] args)
at MS.Internal.Xaml.Runtime.PartialTrustTolerantRuntime.CreateInstance(XamlType xamlType, Object[] args)
at System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(ObjectWriterContext ctx)
at System.Xaml.XamlObjectWriter.WriteEndObject()
at System.Xaml.XamlWriter.WriteNode(XamlReader reader)
at System.Windows.Markup.WpfXamlLoader.TransformNodes(XamlReader xamlReader, XamlObjectWriter xamlWriter, Boolean onlyLoadOneNode, Boolean skipJournaledProperties, Boolean shouldPassLineNumberInfo, IXamlLineInfo xamlLineInfo, IXamlLineInfoConsumer xamlLineInfoConsumer, XamlContextStack`1 stack, IStyleConnector styleConnector)
at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
at System.Windows.Markup.WpfXamlLoader.LoadDeferredContent(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings parentSettings, Uri baseUri)
at System.Windows.ResourceDictionary.CreateObject(KeyRecord key)
at System.Windows.ResourceDictionary.RealizeDeferContent(Object key, Object& value, Boolean& canCache)
at System.Windows.ResourceDictionary.GetValueWithoutLock(Object key, Boolean& canCache)
at System.Windows.ResourceDictionary.GetValue(Object key, Boolean& canCache)
at System.Windows.ResourceDictionary.GetValueWithoutLock(Object key, Boolean& canCache)
at System.Windows.ResourceDictionary.GetValue(Object key, Boolean& canCache)
at System.Windows.DeferredResourceReference.GetValue(BaseValueSourceInternal valueSource)
at System.Windows.DeferredAppResourceReference.GetValue(BaseValueSourceInternal valueSource)
at System.Windows.DependencyPropertyChangedEventArgs.get_NewValue()
at System.Windows.Controls.ContentControl.OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
at System.Windows.Baml2006.WpfKnownMemberInvoker.SetValue(Object instance, Object value)
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(XamlMember member, Object obj, Object value)
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(Object inst, XamlMember property, Object value)
at MS.Internal.Xaml.Runtime.PartialTrustTolerantRuntime.SetValue(Object obj, XamlMember property, Object value)
at System.Xaml.XamlObjectWriter.SetValue(Object inst, XamlMember property, Object value)
at System.Xaml.XamlObjectWriter.Logic_ApplyPropertyValue(ObjectWriterContext ctx, XamlMember prop, Object value, Boolean onParent)
at System.Xaml.XamlObjectWriter.Logic_DoAssignmentToParentProperty(ObjectWriterContext ctx)
at System.Xaml.XamlObjectWriter.Logic_AssignProvidedValue(ObjectWriterContext ctx)
at System.Xaml.XamlObjectWriter.WriteEndMember()
at System.Xaml.XamlWriter.WriteNode(XamlReader reader)
at System.Windows.Markup.WpfXamlLoader.TransformNodes(XamlReader xamlReader, XamlObjectWriter xamlWriter, Boolean onlyLoadOneNode, Boolean skipJournaledProperties, Boolean shouldPassLineNumberInfo, IXamlLineInfo xamlLineInfo, IXamlLineInfoConsumer xamlLineInfoConsumer, XamlContextStack`1 stack, IStyleConnector styleConnector)
at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
at OMS_Pro.WPF.UI.Admin.Admin_Manager.InitializeComponent() in e:\vs_project\OMSPro\OMS_Pro.WPF\UI\Admin\Admin_Manager.xaml:line 1
at OMS_Pro.WPF.UI.Admin.Admin_Manager..ctor() in E:\vs_project\OMSPro\OMS_Pro.WPF\UI\Admin\Admin_Manager.xaml.cs:line 373
InnerException:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resource\lang\Turkish.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
切换的时候执行语句是这个:
Application.Current.Resources.MergedDictionaries[0] = new ResourceDictionary(){ Source = new Uri(@"Resource\lang\" + CmboxChangeLanguage.SelectedValue.ToString() + ".xaml", UriKind.Relative)};
我打算安装一个土耳其文的操作系统,看看是不是因为语言字符导致了.net 无法识别。
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resource\lang\Turkish.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>Souce=什么的时候,最好使用Source="/Dll名称;component/路径/文件名",否则不利于重构.切换语言的代码“Application.Current.Resources.MergedDictionaries[0] = new ResourceDictionary(){ Source = new Uri(@"Resource\lang\" + CmboxChangeLanguage.SelectedValue.ToString() + ".xaml", UriKind.Relative)};”
也不能用0这样的索引硬编码,应该直接添加新的资源字典,然后移除原来的资源字典。