Display a content dialog

Eduardo Gomez 3,651 Reputation points
2023-07-05T20:55:16.99+00:00

In winUI, for some reason, to display a Content Dialog, you need an "xaml root"

like this

private async void ShowDialog_Click(object sender, RoutedEventArgs e)
{
    ContentDialog dialog = new ContentDialog();

    // XamlRoot must be set in the case of a ContentDialog running in a Desktop app
    dialog.XamlRoot = this.XamlRoot;
    dialog.Style = Application.Current.Resources["DefaultContentDialogStyle"] as Style;
    dialog.Title = "Save your work?";
    dialog.PrimaryButtonText = "Save";
    dialog.SecondaryButtonText = "Don't Save";
    dialog.CloseButtonText = "Cancel";
    dialog.DefaultButton = ContentDialogButton.Primary;
    dialog.Content = new ContentDialogContent();

    var result = await dialog.ShowAsync();
}


but because I am using MVVM I want my view Model, to open the dialog. So, I am passing the xamlRoot to the view model.

But when I pass it, is null, So cannot open my dialog

and the strange part is, that the "xamroot" in the window is also null

My Login Window

  public sealed partial class LoginWindow : Window {

        public LoginWindowViewModel ViewModel { get; }

        public LoginWindow(LoginWindowViewModel viewModel) {
            InitializeComponent();

            ViewModel = viewModel;
            viewModel.xamlRoot = Content.XamlRoot;

            ExtendsContentIntoTitleBar = true;
            SetTitleBar(AppBar);
        }
    }
}

VM

  public partial class LoginWindowViewModel : ObservableObject {

        private readonly ILocation _location;
        private string _actualLocation;

        public XamlRoot xamlRoot { get; set; }

        public LoginWindowViewModel(ILocation location) {
            _location = location;
            GetLocationRequest();
     
    }

        private async void GetLocationRequest() {
            Geolocator geolocator = new() {
                DesiredAccuracy = PositionAccuracy.High,
                DesiredAccuracyInMeters = 10,
            };
            Geoposition position = await geolocator.GetGeopositionAsync();
            _actualLocation = await _location.GetAddress(position.Coordinate.Latitude, position.Coordinate.Longitude);
        }

        [RelayCommand]
        private async Task OpenRegisterDialogAsync() {

            var registerVM = new RegisterWindowViewModel(_location);
            var registerView = new RegisterWindow(registerVM);


        }
    }
}

my registe contentdialog

<ContentDialog
    x:Class="Demy.View.RegisterWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:demy="using:Demy"
    xmlns:local="using:Demy.View"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">


    <StackPanel
        Grid.Row="1"
        Width="600"
        HorizontalAlignment="Center"
        VerticalAlignment="Center"
        Spacing="20">

        <TextBox
            PlaceholderText="First name"
            Text="{x:Bind ViewModel.User.Name}" />

        <TextBox
            PlaceholderText="Second name"
            Text="{x:Bind ViewModel.User.SecondName}" />

        <TextBox
            PlaceholderText="Phone Number"
            Text="{x:Bind ViewModel.User.Phone}" />

        <TextBox
            PlaceholderText="Email Address"
            Text="{x:Bind ViewModel.User.Email}" />

        <PasswordBox
            Password="{x:Bind ViewModel.User.Password}"
            PasswordRevealMode="Peek"
            PlaceholderText="Password" />

        <PasswordBox
            Password="{x:Bind ViewModel.User.ConfirmPassword}"
            PasswordRevealMode="Peek"
            PlaceholderText="Confirm password" />

        <Button Command="{x:Bind ViewModel.RegisterAsyncCommand}" />
    </StackPanel>
</ContentDialog>

Windows development Windows App SDK
0 comments No comments
{count} votes

Accepted answer
  1. Castorix31 90,521 Reputation points
    2023-07-06T10:57:57.0633333+00:00

    You can use Loaded event on the Content.

    Something like :

                InitializeComponent();
                var rootElement = this.Content as FrameworkElement;
                if (rootElement != null)
                    rootElement.Loaded += Root_Loaded;
    
            private void Root_Loaded(object sender, RoutedEventArgs e)
            {
                var root = this.Content.XamlRoot;
                //...
            }
    
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Jeanine Zhang-MSFT 11,356 Reputation points Microsoft External Staff
    2023-07-06T02:28:07.16+00:00

    Hello,

    Welcome to Microsoft Q&A!

    According to the Doc: UIElement.XamlRoot Property

    When a UIElement is first created, XamlRoot returns null. After it's parented to a live XAML object, it will return the same XamlRoot object as its parent. A common scenario for XamlRoot to be null is if you access the property from the constructor of your app.

    According to your code, you put the XamlRoot in the constructor of Window, so the XamlRoot is null.

    I suggest you should place XamlRoot outside the constructor.

    Thank you.

    Jeanine


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.