C# WinUI 3 Desktop Application Issue with ContentDialog and the XamlRoot

1.2k Views Asked by At

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}");
        }
    }
1

There are 1 best solutions below

0
On

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();
}