0

I am building a C# WinUI 3 desktop app running on Windows 10. I want to use a contentdialog to display error messages.

I am calling this method from multiple catch clauses:

private async void DisplayErrorDialog(string content)
{

    ContentDialog ErrorDialog = new ContentDialog()
    {
        Title = "* Error *",
        Content = content,
        CloseButtonText = "Ok"
    };

    // XamlRoot must be set in the case of a ContentDialog running in a Desktop app
    ErrorDialog.XamlRoot = this.Content.XamlRoot;
    ContentDialogResult result = await ErrorDialog.ShowAsync();
}

Here is how I call the method:

    catch (SqlException Sql_Error)
    {
        Debug.WriteLine($"Hello SQL error GetSQLData_App_View_Results_2020: {Sql_Error.Message}");
        DisplayErrorDialog($"GetSQLData_App_View_Results_2020 (SQL Error): {Sql_Error.Message}");
    }
    catch (Exception Other_Error)
    {
        Debug.WriteLine($"Hello Other error GetSQLData_App_View_Results_2020: {Other_Error.Message}");
        DisplayErrorDialog($"GetSQLData_App_View_Results_2020 (Other Error): {Other_Error.Message}");
    }
}

I have many other contentdialogs working successfully within my application. I wanted/needed to test this error contentdialog so I explicitly threw an exception this way:

throw new Exception("SQL test exception #1");

The throw does work and the catch clause 'catches' the exception. However I am getting this error in the contentdialog:

Exception thrown at 0x00007FFFD5FE3FA9 (KernelBase.dll) in MetricReporting.exe: WinRT originate error - 0x80070057 : 'This element is already associated with a XamlRoot, it cannot be associated with a different one until it is removed from the previous XamlRoot.'.

Code Showing The Error

I cannot figure this out. I am a beginner C# and WinUI 3 developer. Thank you for your help and guidance.

  • Thank you Andrew for your observation.

Here is more of my code:

public pageResults()
{
    
    this.InitializeComponent();
    Debug.WriteLine($"@@@ --- InitializeComponents() Completed --- @@@");

    FetchSQLData_Ref_Metric();
    FetchSQLData_Ref_Metric_MarketID();
    FetchSQLData_StateCodes();
    FetchSQLData_MetricYear();
    FetchSQLData_Results();
    Display_Results();
}

I am doing a lot of sql fetching of data into datatables and then I display the datatable in a datagrid on the page, which is part of a navigationview.

I inserted the 'throw' inside of a method that is inside of 'FetchSQLData_Results()'

private void FetchSQLData_Results()
{
    string metricYear = string.Empty;
    // Pre-load all views into their own separate datatables. Each views represents a metric year.
    // At this time there are views for 2020, 2021, and 2022
    foreach (DataRow row in dtMetricYear.Rows)
    {
        metricYear = row["metricyear"].ToString();
        GetSQLData_App_View_Results_(metricYear);
    }
}

private void GetSQLData_App_View_Results_(string metricYear)
{
    // Load datatables with existing views
    switch (metricYear)
    {
        case "2020":
            GetSQLData_App_View_Results_2020();
            break;
        case "2021":
            GetSQLData_App_View_Results_2021();
            break;
        case "2022":
            GetSQLData_App_View_Results_2022();
            break;
        case "2023":
            break;
        case "2024":
            break;
        default:
            break;
    }
}

The throw is here:

public void GetSQLData_App_View_Results_2020()
{
    try
    {
        using (SqlConnection con = new SqlConnection("Data Source = xxxx; Initial Catalog = xxxx; Integrated Security = True; Connect Timeout = 15; Encrypt = False; TrustServerCertificate = True; ApplicationIntent = ReadWrite; MultiSubnetFailover = False"))
        {
            **//throw new Exception("SQL test exception #1");**

            //Prepare sql
            //string sql = "select * from dbo.app_emb_prd_lvl_results_2020 order by metric_id";
            string sql = "select * from app_emb_prd_lvl_results_2020 v join dbo.Ref_Metric r on v.metric_id = r.Metric_ID order by v.metric_id";

            SqlCommand cmd = new SqlCommand(sql, con);

            cmd.CommandType = System.Data.CommandType.Text;
            //Open the connection
            con.Open();
            // Create adapter and fill the datatable with returned data from sql command
            using (SqlDataAdapter adap = new SqlDataAdapter(cmd))
            {
                dtResults2020.Clear();
                adap.Fill(dtResults2020);

                try
                {.. intentionally left blank ..}

                catch (Exception List_Error)
                {
                        Debug.WriteLine($"List error GetSQLData_App_View_Results_2020: {List_Error.Message}");
                }
                        
                    
                    Debug.WriteLine($"GetSQLData_App_View_Results_2020 Completed");
                    
                } // end using sql adapter
            } // end using sql connection
        }
        catch (SqlException Sql_Error)
        {
            Debug.WriteLine($"Hello SQL error GetSQLData_App_View_Results_2020: {Sql_Error.Message}");
            DisplayErrorDialog($"GetSQLData_App_View_Results_2020 (SQL Error): {Sql_Error.Message}");
        }
        catch (Exception Other_Error)
        {
            Debug.WriteLine($"Hello Other error GetSQLData_App_View_Results_2020: {Other_Error.Message}");
            DisplayErrorDialog($"GetSQLData_App_View_Results_2020 (Other Error): {Other_Error.Message}");
        }
    }
4
  • My first guess is that you're trying to show the ContentDialog before XamlRoot is ready. Can you share more code about when you're throwing the exception? Commented Nov 9, 2022 at 8:18
  • @AndrewKeepCoding - I have added more of my code. I don't know exactly how the XamlRoot works, but you have made me think that I need to restructure my code on this page so that the page is 'displayed' first, then the sql fetches should occur. I'll try that. What do you think? Thanks again! Commented Nov 9, 2022 at 16:57
  • Generally, you should not invoke complex logic in a constructor, like you to in your "pageResults' constructor. See also this link: github.com/microsoft/microsoft-ui-xaml/issues/… Commented Nov 17, 2022 at 12:47
  • Thank you @Martin for your advice. I'll check out that link you embedded. Thanks again! Commented Nov 28, 2022 at 18:02

1 Answer 1

0

As I mentioned in the comments, XamlRoad might not be ready. Try fetching your data in Loaded instead of the constructor.

public pageResults()
{
    this.InitializeComponent();
    this.Loaded += pageResults_Loaded;
    Debug.WriteLine($"@@@ --- InitializeComponents() Completed --- @@@");
}

private void pageResults_Loaded(object sender, RoutedEventArgs e)
{
    FetchSQLData_Ref_Metric();
    FetchSQLData_Ref_Metric_MarketID();
    FetchSQLData_StateCodes();
    FetchSQLData_MetricYear();
    FetchSQLData_Results();
    Display_Results();
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.