程序在app.xaml中用ResourceDictionary来支持多语言界面显示,控件用DynamicResource方式定位语言文件中相应的内容。默认英语,用户登录成功后根据身份打开对应的功能窗口操作没有问题,但是切换到土耳其语后,在打开功能窗口时,InitializeComponent()方法报错,我用F11跟踪,还不清楚是到哪一步和哪个对象的错误。
我的疑问是:
1 有什么办法能定位到空对象?或者能知道在第几行代码出错?有没有比较好的辅助工具来调试程序?
2 wpf在切换显示语言的时候,通常会发生什么意外?
3 InitializeComponent()中程序做了一些什么是否能知道?能不能很详细的看到它一步一步执行了什么代码?
谢谢啦

解决方案 »

  1.   

    InitializeComponent()
    是来构造界面的 ,可能是某个对象未实例化 ,猜测而已 
      

  2.   

    谢谢saybookcat。
    我再补充一下,刚才我去掉了语言文件中的内容,显示了空对象的名称。我感到很奇怪,InitializeComponent为什么会去调用cs文件中的方法,比如,cs中我创建了一个方法,往控件ComboBox中添加item,叫AddItem()。执行的先后顺序是InitializeComponent();AddItem();按照道理,界面上应该先会生成一个ComboBox,等InitializeComponent全部完成后,再执行AddItem()方法,但是InitializeComponent的时候就会去添加item,显然,这个时候还没有ComboBox。谁能详细的解释一下InitializeComponent会发生这种情况的原因?谢谢
      

  3.   

    在程序的目录下有个obj的文件夹,在obj/debug/下有个你对应xmal文件的*.g.cs
    这个文件是解析xaml的
    至于如何调试xaml,只能看堆栈信息了。。或者打印出Exception的detail.
      

  4.   

    你2楼说的情况,为了保险应该使用
    this.Loaded += new RoutedEventHandler(Window1_Loaded);在Window1_Loaded添加AddItem的方法
      

  5.   

    比如,cs中我创建了一个方法,往控件ComboBox中添加item,叫AddItem()。执行的先后顺序是InitializeComponent();AddItem();按照道理,界面上应该先会生成一个ComboBox
    这是不对的,InitializeComponent只是把控件的位置大小等确定了只有在调用Render后才会在界面上呈现。
    你可以重载Window的protected override void OnRender(DrawingContext drawingContext)
    {
    base.OnRender(drawingContext);
    }方法,这是绘制Window时调用的
    至于我前面提到的Loaded,则是比OnRender还要之后的。
      

  6.   

    回复viki117:  加载没有问题,界面是正常的。回复fallincloud:我修改了,貌似不行。
    public 构造函数
    {
          this.loaded += new RoutedEventHandler(window_load);
          InitializeComponent();
    }
    private void window_load(object sender, RoutedEventArgs e)
    {
        AddItem();
    }
    如上所示,是这样吗?执行到InitializeComponent还是报错。
      

  7.   

    在一个winform中有4个tab切换,每个tab中都有一个datagrid,一个选择每页显示多少条记录的控件combobox,有4个选项
    <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: 
      

  8.   

    如果可以的话,把相关代码发到我邮箱里[email protected]
      

  9.   

    app.xaml中是这样
    <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 无法识别。
      

  10.   

    XML,多国语言文件有错误。需要仔细检查
      

  11.   

    谢谢siskinbin,我后来检查了语言包文件,果然发现有一个key是为空,漏了内容,补充后发现问题解决,结贴。
      

  12.   

    <ResourceDictionary>
                <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这样的索引硬编码,应该直接添加新的资源字典,然后移除原来的资源字典。
      

  13.   

    漏了key的情况,应该会出现“Cannot find resource named '{window1.none}'. Resource names are case sensitive.  Error at object 'System.Windows.Controls.TextBlock' in up file 'WpfApplication1;component/window1.xaml' Line 44 Position 16.”类似的提示,在xaml中使用语言的资源时,应该使用DynamicResource 这样最多是字符显示为空,永远不会出错