0

Assuming I have a window that looks something like this:

<Window>

    <Window.Resources>
    
        <ResourceDictionary>
        
            <controllers:MainWindowController x:Key="Controller" />
        
        </ResourceDictionary>
    
    </Window.Resources>
    
    <Window.DataContext>
    
        <Binding Source="{StaticResource Controller}" />
    
    </Window.DataContext>
    
    <Grid Margin="5">
    
        <Grid.RowDefinitions>
            
            <RowDefinition />
            
            <RowDefinition Height="Auto" />
        
        </Grid.RowDefinitions>
        
        <ListBox Grid.Row="0"
                 Margin="0, 0, 0, 2.5"
                 ItemsSource="{Binding Users}"
                 SelectedItem="{Binding SelectedUser, Mode=OneWayToSource}" />
                 
        <Button Grid.Row="1"
                Margin="0, 2.5, 0, 0"
                Command="{Binding DisplayUserInfoCommand}" />
    
    </Grid>

</Window>

and the MainWindowController class is something like:

public sealed class MainWindowController : ReactiveObject
{
    public ObservableCollection<User> Users { get; } = new ObservableCollection<User>();
    
    public User SelectedUser { get; set; }
    
    public ReactiveCommand<Unit, Unit> DisplaySelectedUserInfoCommand { get; }
    
    public MainWindowController()
    {
        DisplaySelectedUserInfoCommand = ReactiveCommand.Create(DisplaySelectedUserInfoCommandHandler);
    }
    
    private void DisplaySelectedUserInfoCommandHandler()
    {
        if (SelectedUser == null) return;
        
        // TODO: pass SelectedUser to the newly created UserInfoWindow.
        _ = new UserInfoWindow().ShowDialog();
    }
}

the User is a record that looks like this:

public sealed record User(string Name, string Email, string Phone);

and the UserInfoWindow is something like:

<Window>

    <Window.Resources>
    
        <ResourceDictionary>
        
            <controllers:UserInfoWindowController x:Key="Controller" />
        
        </ResourceDictionary>
    
    </Window.Resources>
    
    <Window.DataContext>
    
        <Binding Source="{StaticResource Controller}" />
    
    </Window.DataContext>
    
    <Grid Margin="5">
    
        <Grid.RowDefinitions>
            
            <RowDefinition />
            
            <RowDefinition />
        
            <RowDefinition />
        
        </Grid.RowDefinitions>
        
        <Label Grid.Row="0"
               Margin="0, 0, 0, 2.5"
               Content="{Binding User.Name}" 
               ContentStringFormat="Name: {0}" />
               
        <Label Grid.Row="1"
               Margin="0, 2.5, 0, 2.5"
               Content="{Binding User.Email}" 
               ContentStringFormat="Email: {0}" />
               
        <Label Grid.Row="2"
               Margin="0, 2.5, 0, 0"
               Content="{Binding User.Phone}" 
               ContentStringFormat="Phone: {0}" />
    
    </Grid>

</Window>

and the UserInfoWindowController is something like this:

public sealed class UserInfoWindowController : ReactiveObject
{
    private User _user;
    
    public User User
    {
        get => _user;
        
        set => this.RaiseAndSetIfChanged(ref _user, value);
    }
}

how can I pass the SelectedUser from the MainWindowController to the newly created UserInfoWindow without manually passing a new instance of UserInfoWindowController to it upon its creation or setting the DataContext via code?

Notes:

  • The XAML code above isn't "complete" since I have stripped some unnecessary attributes for the sake of keeping the post short.

  • I've omitted the using directives from the C# code for the same reason as above.

  • I'm using ReactiveUI.

  • My WPF application is using .NET 5.

7
  • 1
    UserInfoWindow ViewModel is irrelevant with a selected user isn't it? So its constructor should ask for a UserInfo object. Commented Jun 22, 2021 at 0:55
  • The essential details of your implementation are missing to answer your question. First of all, these are: How do you create and display the second Window? This moment is important, since the transfer of data to it should be carried out exactly at this moment. Commented Jun 22, 2021 at 6:37
  • The second important point. Since the user's selection happens in the MainWindowController, why didn't you declare a property of type UserInfoWindowController for the selected user here? Then the second Window could receive this controller into its DataContext. Commented Jun 22, 2021 at 6:41
  • Third point. As I understand it, you do not provide for several main Windows. And the created instance of MainWindowController must exist for the entire duration of the application session. Why then do you declare the MainWindowController instance in the Window resources and not in the App Resources? Commented Jun 22, 2021 at 6:43
  • "The essential details of your implementation are missing to answer your question. First of all, these are: How do you create and display the second Window? This moment is important since the transfer of data to it should be carried out exactly at this moment." - @EldHasp what "essential" details are missing? I've clearly shown that I create and show the second window by using _ = new UserInfoWindow().ShowDialog() in the examples above. Commented Jun 22, 2021 at 8:00

1 Answer 1

1

If I understood your code correctly and additional explanations in the comments, then I think this solution should work:

    private void DisplaySelectedUserInfoCommandHandler()
    {
        if (SelectedUser == null) return;
        
        // TODO: pass SelectedUser to the newly created UserInfoWindow.
        var win = new UserInfoWindow();

        var contr = (UserInfoWindowController) win.Resources["Controller"];
        contr.User = SelectedUser;

        win.ShowDialog();
    }

Another possible option:

   public UserInfoWindowController(User user)
     : this()
   {
        var contr = (UserInfoWindowController) Resources["Controller"];
        contr.User = user;
   }
    private void DisplaySelectedUserInfoCommandHandler()
    {
        if (SelectedUser == null) return;
        
        // TODO: pass SelectedUser to the newly created UserInfoWindow.
        _ = new UserInfoWindow(SelectedUser).ShowDialog();
    }
Sign up to request clarification or add additional context in comments.

2 Comments

I was already using something similar to the second solution but instead of using (UserInfoWindowController)Resources["Controller"] I was doing ((UserInfoWindowController)DataContext).User = user
If there is nothing else in the UserInfoWindowController class besides the User property, then yes - you can do that.

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.