1

I have a ContentDialog triggered when a user clicks on a row in a DataGrid. The primary goal of the ContentDialog is to allow the user to enter and save a comment via a textbox control named 'Cmnt_Apprvl_Mgmt' in the ContentDialog. The logic is working now.

Now I would like some of the data from the clicked row from the DataGrid to appear in the ContentDialog. I have not been able to figure out how to do it.

I pass 'rowModel' (data from the datagrid) as a parameter to the new contentdialog (v3). I would like any previous comment already entered for a particular row to populate the textbox 'Cmnt_Apprvl_Mgmt' in the ContentDialog.

Thank you in advance StackOverflow-contributors, you have been so helpful to me during this project. It is greatly appreciated.

My code: (xaml)

<ContentDialog x:Name="MgmtApprovalDialog"
               Title = "Enter Management Approval Comment"
               PrimaryButtonText="Save"
               CloseButtonText="Cancel"
               Opened="MgmtApprovalDialog_Opened"
               PrimaryButtonClick="MgmtApprovalDialog_PrimaryButtonClick">
    <StackPanel>
        <TextBox x:Name="Cmnt_Apprvl_Mgmt" PlaceholderText="Enter Comment" Margin="0 0 0 0" TextWrapping="Wrap" Height="80" TextChanged="Cmnt_Apprvl_Mgmt_TextChanged"/>
        <TextBlock x:Name="errorTextBlock" Margin="0 10 0 5" FontWeight="Bold" FontStyle="Oblique"/>
        <!-- Content body -->
        <TextBlock Name="body" TextWrapping="Wrap">
            <TextBlock.Text>
                When a target is not met, a comment from management is required (long and detailed)                       
            </TextBlock.Text>
        </TextBlock>
    </StackPanel>
</ContentDialog>

C#

private void MgmtApprovalDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
            // Ensure the comment field is empty. If a required field
            // is empty, set args.Cancel = true to keep the dialog open.
            if (string.IsNullOrEmpty(Cmnt_Apprvl_Mgmt.Text))
            {
                args.Cancel = true;
                errorTextBlock.Text = "Comment is required.";
            }
}
            
private void DataGrid_Detail_PointerReleased(object sender, PointerRoutedEventArgs e)
            {
                DataGridRow clickedRow = FindParent<DataGridRow>((UIElement)e.OriginalSource);
                if (clickedRow != null)
                {
                    Approvals rowModel = (Approvals)clickedRow.DataContext;
                    // Do stuff
                    // DisplayCommentDialog();
                    //DisplayCommentDialog_v2(rowModel);
                    DisplayCommentDialog_v3(rowModel);
                }
            }

        // +---------------------------------------------------------
        // | DISPLAY COMMENT DIALOG V3
        // +---------------------------------------------------------
        private async void DisplayCommentDialog_v3(Approvals rowModel)
        {
            ContentDialogResult result = await MgmtApprovalDialog.ShowAsync();
            if (result == ContentDialogResult.Primary)
            {
                // Save button clicked
                Debug.WriteLine($"+-------------------------------------------------------------------");
                Debug.WriteLine($"| Hello - inside DisplayCommentDialog_v3 Primary Button Clicked!");
                Debug.WriteLine($"| Hello - Comment ID  : {rowModel.Comment_ID}");
                Debug.WriteLine($"| Hello - Comment Text: {Cmnt_Apprvl_Mgmt.Text}");
                Debug.WriteLine($"+-------------------------------------------------------------------");
                SaveMgMtApprovalComment(rowModel.Comment_ID, Cmnt_Apprvl_Mgmt.Text);
                // Before refreshing the DataGrid_Detail you must re-pull from the server (this may be a design flaw.)
                GetSQLData_Approvals();
                // Refresh DataGrid_Detail so the user can see what was just entered
                PopulateApprovalDetDG(v_product);
            }
            else
            {
                // User pressed Cancel, ESC, or the back arrow.
                // Terms of use were not accepted.
                Debug.WriteLine($"+-------------------------------------------------------------------");
                Debug.WriteLine($"| Hello - inside DisplayCommentDialog_v3 (Cancel, ESC, or back arrow)");
                Debug.WriteLine($"+-------------------------------------------------------------------");
            }
        }
LennyL
  • 225
  • 3
  • 9
  • Binding, Binding, Binding. WinUI3 (like all XAMLs techs) is totally unusable w/o abusing data binding. Just set MgmtApprovalDialog.DataContext to rowModel and bind MgmtApprovalDialog to rowmodel's properties. https://stackoverflow.com/questions/75149524/bind-winui-3-contentdialog-datacontext-to-property – Simon Mourier Jun 17 '23 at 08:17
  • Thank you very much for your reply Simon Mourier! I had seen your other post, and I tried to implement it but could not make it work.Then I posted my question. I am still a C# newbie. I will be studying your other post so I can understand it. – LennyL Jun 17 '23 at 20:01

1 Answers1

0

Solution 1: DataContext and Bindings

An easy solution is the one proposed by Simon Mourier in his comment.

Simply set the DataContext of your ContentDialog to the selected item to enable binding on its properties.

private async void DisplayCommentDialog_v3(Approvals rowModel)
{
    MgmtApprovalDialog.DataContext = rowModel;
    ContentDialogResult result = await MgmtApprovalDialog.ShowAsync();

Then, assuming Approvals has a string Comment property, you can use the following binding on your TextBox.

<TextBox Text="{Binding Comment}" (...) />

Solution 2: Subclass ContentDialog

If you don't want to use bindings, you can also create a class derived from ContentDialog which allows you to add custom logic and expose extra members. You can find an example of this here.

In your case it could look like the following.

public sealed partial class ApprovalDialog: ContentDialog
{
    public ApprovalDialog()
    {
        this.InitializeComponent();        
    }

    public void SetComment(string comment)
    {
        Cmnt_Apprvl_Mgmt.Text = comment;
    }
}

Then you would call the extra method before showing the dialog:

private async void DisplayCommentDialog_v3(Approvals rowModel)
{
    // Again, I don't know if `Comment` is the correct property name.
    MgmtApprovalDialog.SetComment(rowModel.Comment);
    ContentDialogResult result = await MgmtApprovalDialog.ShowAsync();

You would also need to change your xaml to include x:Class to specify your custom type.

<ContentDialog x:Class="YourNameSpace.ApprovalDialog"
               x:Name="MgmtApprovalDialog"
               Title = "Enter Management Approval Comment"
      (...)
Batesias
  • 1,914
  • 1
  • 12
  • 22
  • 1
    Thank you Batesias, I implemented solution #1 and it worked! I don't totally understand solution #2 yet, but I will try a stub program to test it out. .... I think I am beginning to understand solution #2 more and more, the more I look at it. Thank you again! I really appreciate your help. – LennyL Jun 17 '23 at 20:06