【问题标题】:XamlParseException on ValidationError when App launching应用程序启动时 ValidationError 出现 XamlParseException
【发布时间】:2013-04-07 14:05:50
【问题描述】:

我创建了一个绑定了一些文本框的 WPF 应用程序。 我使用验证错误来检查值是否正常。验证查找数据库以查看输入的数据是否存在。

如果我输入一个错误值,我的验证错误会捕获错误但没有问题:)

尽管如此,如果我输入了一个合适的值,并且如果我关闭我的应用程序,然后继续我的数据库删除该值,当我重新启动我的应用程序时,最新的数据会被加载,并且在这里......我有一个不错的崩溃:“XamlParseException”。

这个异常是因为我删除了数据中的一个值,并且,当验证寻找我的数据库时,没有找到数据。

我不明白为什么我在启动时会崩溃,但之后却没有。

这是我的验证示例:

    private string m_strCodeIntervenant;
    public string strCodeIntervenant
    {
        get { return m_strCodeIntervenant; }
        set
        {
            m_strCodeIntervenant = value;
            if (m_strCodeIntervenant.Trim() != "")
            {
                if (m_objIntervenant.ReadIntervenantCodebyCode(m_strCodeIntervenant) != 0)
                {
                    throw new ApplicationException(m_strCodeIntervenant.Trim() + " don't exist !");
                }
                FirePropertyChangedEvent("strCodeIntervenant");
            }
            else
            {
                m_objIntervenant.strNom = "";
                m_objIntervenant.strIntervenant = "";
            }
            FirePropertyChangedEvent("objIntervenant.strNom");
        }
    }

这是我的验证 XAML:

<TextBox Grid.Column="1" Name="TextBox_Intervenant" TabIndex="2" VerticalAlignment="Center" Height="20" >
    <TextBox.Text>
        <Binding Path="strCodeIntervenant" >
            <Binding.ValidationRules>
                <ExceptionValidationRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>


---------

<Style TargetType="{x:Type TextBox}">
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <DockPanel LastChildFill="True">
                    <TextBlock Margin="50,0,0,0" DockPanel.Dock="Right"
                    Foreground="Red"
                    FontSize="10pt"
                    Text="{Binding ElementName=MyAdorner,Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
                    </TextBlock>
                    <Border BorderBrush="Red" BorderThickness="1">
                        <AdornedElementPlaceholder Name="MyAdorner" />
                    </Border>
                </DockPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这是我的 XAML.cs(稍微清理一下以获得更好的视图):

public partial class MainWindow : Window
{

    private void InitialiserControles()
    {
        TextBox_Description.Text = string.Empty;
        TextBox_EvtNum.Text = string.Empty;
        TimePicker_Heure.Value = null;
        TextBox_Intervenant.Text = string.Empty;
        TextBox_TypeEvenement.Text = string.Empty;
        TextBloc_Note.Text = string.Empty;
        DateTimePicker_Date.SelectedDate = DateTime.Today;
        DateTimePicker_Relance.SelectedDate = null ;
    }

    public ObservableCollection<Evenement> Collection_Evenements = new ObservableCollection<Evenement>();
    Evenement myEvenement = new Evenement();

    private void MettreAJourTableauEvenements()
    {
        Collection_Evenements = myEvenement.GetEvenementsForCliCode(App.obj_myClient.m_strCode);
        Collection_Evenements.CollectionChanged += Collection_Evenements_CollectionChanged;
        myDataGridEvenements.ItemsSource = Collection_Evenements;
    }

    public MainWindow()
    {
            InitializeComponent();

            this.DataContext = App.obj_myEvenement;

            //Load Evenement in DataGrid
            MettreAJourTableauEvenements();

    }


    private void myDataGridEvenements_SelectedCellsChanged_1(object sender, SelectedCellsChangedEventArgs e)
    {
        // Affiche le code évt sélectionné dans le tableau, dans les champs modifiable ( en haut de l'écran )

        var item = myDataGridEvenements.SelectedItem as Evenement;         
        if ((item != null))
        {
            App.obj_myEvenement.ReadEvenementebyNumero(item.strEvtNumero);
            TextBox_Description.Text = item.strDesignation;
            TextBox_EvtNum.Text = item.strEvtNumeroString;
            TextBox_Intervenant.Text = item.strCodeIntervenant;
            TextBox_TypeEvenement.Text = item.strEvtType;
            TextBloc_Note.Text = item.strNote;
            DateTimePicker_Date.SelectedDate = Evenement.ConvertToDateTimePicker(item.dDate);
            DateTimePicker_Relance.SelectedDate = Evenement.ConvertToDateTimePicker(item.dDateRelance);
            TimePicker_Heure.Value = item.dDate;
        }
    }

    private void Collection_Evenements_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
        {
            (e.OldItems[0] as Evenement).SupprimeEvenement();
            InitialiserControles();
        }
    }

    private void Window_Loaded_1(object sender, RoutedEventArgs e)
    {

        myDataGridEvenements.Focus();
        myDataGridEvenements.SelectedIndex = 0;
        myDataGridEvenements.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));

        Lbl_CliCodeCliDes.Content = App.obj_myClient.m_strCode.Trim() + " - " + App.obj_myClient.m_strNom.Trim();
        Lbl_CliCPostalVille.Content = App.obj_myClient.m_strCodePostal.Trim() + " - " + App.obj_myClient.m_strVille.Trim(); 

        App.obj_Parametres.LoadDataGridParams(myDataGridEvenements);

    }


    private bool IsValid(DependencyObject obj)
    {
        // return false;
        // The dependency object is valid if it has no errors, 
        //and all of its children (that are dependency objects) are error-free.
        return !Validation.GetHasError(obj)&&
        !LogicalTreeHelper.GetChildren(obj)
        .OfType<DependencyObject>()
        .Any(child => !IsValid(child));
    }


}

此崩溃发生在生产“发布”或“调试模式”中。

异常是带有 InnerException = {"TELOU 不存在!"} 的 XamlParseException 不是在文本框(警告标签)旁边显示“TELOU 不存在”,而是不会抛出异常。

有人有什么想法吗?

非常感谢:)

最好的问候,

尼克斯

【问题讨论】:

  • 如果您的应用程序崩溃,那么您应该得到一个异常。发布它也会有帮助。
  • 我编辑了我的帖子:异常是带有 InnerException = {"TELOU don't exist!"} 的 XamlParseException,而不是在文本框(警告标签)旁边显示“TELOU 不存在”,没有抛出异常。
  • 试试这个:(不带引号)
  • 不能编译没有引号! :(
  • 您能否帮助我们了解您的 xaml.cs 的详细信息。您在 xaml 的构造函数中编写了哪些代码,导致崩溃?您可以在构建视图后尝试分配视图模型吗? (假设你在这里了解 MVVM)

标签: c# wpf xaml data-binding validation


【解决方案1】:

XAML 不显示异常,仅在输出窗口中显示。

您的代码抛出错误,但仅显示在输出窗口中。

当异常发生在控件的初始化时,它无法处理并破坏应用程序。

不要抛出异常自行处理错误。

【讨论】:

    【解决方案2】:

    您可能在定义m_strCodeIntervenant 字段的类的构造函数中遇到崩溃。也许某些东西正在使用之前缓存的“好”值,并通过直接设置字段来绕过验证。

    在那里设置断点并分析发生了什么。

    【讨论】:

    • 错误是当我的数据库设置 m_strCodeIntervenant 值时。
    • 当 Xaml 使用它时,您不能在构造函数中抛出异常。请记住,Xaml 只是一种对象序列化语言,未能创建对象将导致 XamlParseException(尽管它有点误导)。如果您必须在构造函数中设置值或最好重构,请进行一些错误检查,以便您不在构造函数中执行业务逻辑。对象创建应该是轻量级的。
    • 但为什么我只在应用程序启动时出现此错误。如果我的所有数据都ok,程序启动whitout问题。我输入了一个错误的数据,验证异常抛出whitout问题。
    【解决方案3】:

    作为急救,请订阅调度程序取消处理异常(最好在 App.xaml.cs 中)

    Msdn 链接 - http://msdn.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception.aspx

    这将帮助您记录崩溃信息。

    尝试这种方法来模板化验证启用的文本框

            <Application.Resources>
      <ControlTemplate x:Key="TextBoxErrorTemplate">
        <DockPanel LastChildFill="True">
          <TextBlock DockPanel.Dock="Right" 
            Foreground="Orange" 
            FontSize="12pt">!!!!</TextBlock>
          <Border BorderBrush="Green" BorderThickness="1">
             <AdornedElementPlaceholder />
          </Border>
        </DockPanel>
      </ControlTemplate>
    </Application.Resources>
    
    <TextBox 
    Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}"> 
    [...]
    <TextBox>
    

    请参阅本文了解更多详情; http://www.codeproject.com/Articles/15239/Validation-in-Windows-Presentation-Foundation

    【讨论】:

    • 您好,我订阅了 te dispatcher,但是为什么我需要在“App_DispatcherUnhandledException()”中写?我使用您的模板,无需更改。对于 codeProjects 链接,我已经阅读过了。
    • App.xaml 是 WPF 应用程序的入口点。因此,在 App.xaml.cs 中处理调度程序未处理的异常可以帮助您避免在所有地方重复它。如 MSDN 文章中所述,您可以进行必要的日志记录并决定进一步的程序。关于您面临的崩溃,Dispatcher 未处理的代码将帮助您在 Visual Studio 中调试以查看堆栈跟踪并找到问题的根本原因。您如何将视图模型分配给您的视图?你是在 xaml 的构造函数里面写的吗?
    • 我有消息了!由于 observableCollection 出现问题。当用户输入数据时,它在TextBox上输入,然后验证可以在textBox附近显示警告标签。但是,当我加载数据时,数据会加载到 observableCollection 中,因此,我需要找到一种方法,以便在从 TextBox 中设置数据时不检查数据。请问你有什么想法吗?谢谢
    • 您是否在视图的构造函数中加载可观察集合?(直接或间接)。 XamlParse 异常的主要原因之一是异常从 Xaml 的构造函数中抛出。您可能会尝试做的第二件事是删除验证并查看文本框绑定是否正常。如果应用程序在从 TextBox 中删除验证后工作,那么问题在于验证模板样式。
    猜你喜欢
    • 2022-01-08
    • 2011-12-09
    • 2015-12-15
    • 2019-04-16
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    • 2014-12-07
    相关资源
    最近更新 更多