show object details of the selected object to another windows Usercontrol use mwwm

I have a person list filled from the database, two fields (id, name) from the person object are databinded with a radiobutton, now when I click on the radiobutton I’m opening a new UserControl and trying to show all the fields of the selected object in the UserControl in detail.
how can I implement this within mvvm?

PersonModel:

    namespace Persons.Models
    {
    class PersonModel
    {
    public int PersonID { get; set; }
    public string Name { get; set; }
    public string Surname {get; set; }
    public string PersonAge { get; set; }
    public string PersonAddress { get; set; }
    public string PersonDepartmentID{ get; set; }
    public string PersonGroupID{ get; set; }
    public string PersonContact{ get; set; }
    public string PersonLevelEductationID{ get; set; }
    public string PersonDivisionID{get; set; }

    public ObservableCollection<PersonModel> Get()
    {
        ObservableCollection<PersonModel> Person_list = new ObservableCollection<PersonModel>();
        var Connect = ConfigurationManager.ConnectionStrings["MysqlConnection"].ConnectionString;
        using (var conn = new MySqlConnection(Connect))
        using (var command = new MySqlCommand())
        {
            conn.Open();
            command.Connection = conn;
            command.CommandText = @"SELECT person.id, person.name, person.surname, person.address, person.age, person.contact department.name AS 'department', group.name AS 'group', eductation.lavel division.name AS 'division' FROM person
            LEFT JOIN department ON department.id = person.departmentID LEFT JOIN group ON group.id = person.groupID LEFT JOIN eductation ON eductation.id = person.eductationLavelID LEFT JOIN division ON division.id = person.divisionID";
            MySqlDataReader reader = command.ExecuteReader();
            while (reader.Read())
            {
                Person_list.Add(new PersonModel()
                {
                    PersonID = (int)reader["id"],
                    Name = (string)reader["name"],
                    Surname = (string)reader["surname"],
                    PersonAge = (int)reader["age"],
                    PersonAddress = (string)reader["address"],
                    PersonDepartmentID = (string)reader["department"],
                    PersonGroupID= (string)reader["group"],
                    PersonContact = (string)reader["contact"],
                    PersonLevelEductationID = (string)reader["lavel"],
                    PersonDivisionID = (string)reader["division"]
                }
                    ) ; 
            }
            reader.Close();
            conn.Close();
        }
        return Person_list;
    }
  }
}

ViewModels

namespace Persons.ViewModels
{
 class PersonViewModel : ViewModelBase
{
private ObservableCollection<PersonModel> _personList;
private readonly PersonModel _person_Model;

public ObservableCollection<PersonModel> PersonItems
    {
        get => _personList;
        set
        {
            if (_personList!= value)
            {
                _personList = value;
                OnpropertyChanged(nameof(PersonItems));
            }
        }
    }

public PersonViewModel()
    {
        _person_Model= new PersonModel();
        _personList= _person_Model.Get();
    }
 }

}

Main UserControl :

 <ScrollViewer 
            VerticalScrollBarVisibility="Auto">
            <ItemsControl ItemsSource="{Binding PersonItems}">
                <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border 
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="auto"/>
                                    <RowDefinition Height="auto"/>
                                </Grid.RowDefinitions>

                             <RadioButton
                             Content="{Binding Name}"     
                             CommandParameter="{Binding Name}"
                             Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.ShowPageCommand}"
                             Style="{StaticResource ItemsButtonStyle}"/>
                            </Grid>
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>

And New UserControl

                   <ScrollViewer 
                    VerticalScrollBarVisibility="Auto">
                    <ItemsControl ItemsSource="{Binding PersonItems}" BorderBrush="White">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Border 
                                    Width="600"
                                    MaxHeight="800">
                                <Grid>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="auto"/>
                                        </Grid.RowDefinitions>

                                    <TextBlock 
                                    HorizontalAlignment="Left"
                                    Grid.Row="1"
                                    Grid.Column="0"
                                    Text="Name:" />

                                    <TextBlock
                                    HorizontalAlignment="Right"
                                    Grid.Row="1"
                                    Grid.Column="0"
                                    Text="{Binding Name}" />

                                    <TextBlock 
                                    HorizontalAlignment="Left"
                                    Grid.Row="2"
                                    Text="Surname :" />

                                    <TextBlock
                                    HorizontalAlignment="Right"
                                    Grid.Row="2"
                                    Text="{Binding Surname}"/>
                                    
                                    <TextBlock 
                                    HorizontalAlignment="Left"
                                    Grid.Row="3"
                                    Text="PersonAge :" />

                                    <TextBlock
                                    HorizontalAlignment="Right"
                                    Grid.Row="3"
                                    Text="{Binding PersonAge }"/>

                                    <TextBlock 
                                    HorizontalAlignment="Left"
                                    Grid.Row="4"
                                    Text="Person Address:" />

                                        <TextBlock
                                    HorizontalAlignment="Right"
                                    Grid.Row="4"
                                    Text="{Binding PersonAddress }"/>

                                    <TextBlock 
                                    HorizontalAlignment="Left"
                                    Grid.Row="6"
                                    Text="Department:" />

                                    <TextBlock
                                    HorizontalAlignment="Right"
                                    Grid.Row="6"
                                    Text="{Binding PersonDepartmentID}"/>
                                    
                                      ........
                                    <TextBlock 
                                    HorizontalAlignment="Left"
                                    Grid.Row="9"
                                    Text="Eductation :" />

                                    <TextBlock
                                    HorizontalAlignment="Right"
                                    Grid.Row="9"
                                    Text="{Binding PersonLevelEductationID}"/>

                                    </Grid>
                                </Border>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>

And Commands

  namespace Persons.ViewModels
   {
  class NavigationViewModel : INotifyPropertyChanged
    {
    
        public NavigationViewModel()
        {
            // Set Startup Page
            SelectedViewModel = new StartupViewModel();
        
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        }

        // Select ViewModel
        private object _selectedViewModel;
        public object SelectedViewModel
        {
            get => _selectedViewModel;
            set { _selectedViewModel = value; OnPropertyChanged("SelectedViewModel"); }
        }
        public void CrudView()
        {
            SelectedViewModel = new CrudPage();    // new usercontrol
        }
        private ICommand _CrudCommand;
        public ICommand ShowPageCommand
        {
            get
            {
                if (_CrudCommand == null)
                {
                    _CrudCommand = new RelayCommand(param => CrudView());
                }
                return _CrudCommand;
            }
        }
      
        // Close App
        public void CloseApp(object obj)
        {
            MainWindow win = obj as MainWindow;
            win.Close();
        }

        // Close App Command
        private ICommand _closeCommand;
        public ICommand CloseAppCommand
        {
            get
            {
                if (_closeCommand == null)
                {
                    _closeCommand = new RelayCommand(p => CloseApp(p));
                }
                return _closeCommand;
            }
        }
       }

Class RelayCommand

 namespace Persons.Utilities
 {
 public class RelayCommand : ICommand
{
    private Action<object> execute;
    private Func<object, bool> canExecute;

    public RelayCommand(Action<object> execute)
    {
        this.execute = execute;
        canExecute = null;
    }

    public RelayCommand(Action<object> execute, Func<object, bool> canExecute)
    {
        this.execute = execute;
        this.canExecute = canExecute;
    }


    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public bool CanExecute(object parameter)
    {
        return canExecute == null || CanExecute(parameter);
    }

    public void Execute(object parameter)
    {
        execute(parameter);
    }
}

I apologize for the long code!

22

What you are after is called master-detail view. You can achieve this by using a ContentControl to display the details view.
You would assign the data model for the details view to the ContentControl.Content property and define a DatatTemplate to actually render the view. You assign this template to the ContentControl.Contenttemplate property or define the DataTemplate as implicit so that it will be automatically loaded.

Since loading is triggered by a Button you can pass the details model as command parameter or by binding the ListBox.SelectedItem property to the view model that also defines the ICommand.

Some considerations:

  • ItemsControl should not be wrapped into a ScrollViewer. Instead wrap the ItemsPresenter of the ItemsControl. This way you properly scroll the items and not the ItemsControl. A ListBox comes with a ScrollViewer by default. ListBox is an extended ItemsControl and adds important perfromance features and properties like `SelectedItem that you usually don’t want to miss.
  • Your PersonModel should not access the database to generate a list of its own. Instead, the view model that owns the PersonViewModel must call the application model to return the PersonModel collection. The model internally uses the database or reads/writes from/to a file or service.
  • You don’t have a 1:1 relationship between a control and view model class. In other words, not every control has its own view model. A view model class represents a particular data context. Multiple controls operate with the same data and therefore the same data context. From your data bindings I can tell that the UserControl has the wrong DataContext set. Additionally, you avoid setting the DataContext explicitly and instead let it be inherited.
  • The UserControl should not bind its internals directly to the DataContext. Instead, introduce dependency properties that the internal can bind to. Then bind these dependency properties to the actual DataContext. This is especially important if you want to reuse the control in different places or applications. If you don’t need this flexibility, you can of course continue to hardcode the dependencies into your custom controls. I was just pointing out that this is not the best practice.
  • Try to use composition for your view model classes. For example, you can define a MainViewModel that exposes other view models classes like the PersonViewModel or the NavigationViewModel. Then assign the MainViewModel to the DataContext root (e.g. the MainWindow). This is far easier to maintain and adds flexibility. For example, such a structure would allow you to use dependency injection, since the only view model to inject would be the MainViewModel into the MainWindow.
  • Creating controls, or handling controls in the view model is violating the MVVM design pattern rules.
  • Performing UI logic like opening or closing views in the view model violates the MVVM design pattern. Such code belongs to the view (e.g. code-behind. For example, to close the window or application you can use common event handlers and the Button.Click event or use routed commands and the Button.Command property.
  • You don’t have to explicitly close resources that implement IDisposable. The using-statement will do that for you. Disposing objects will automatically close them and flush buffers e.g. in case of Stream objects.

MainUserControl.xaml
The master view.

<UserControl>

  <!-- 
    Bind to the nested PersonViewModel. 
    You can also consider to Bind ListBox.SelectedItem to the view model. 
  -->
  <ListBox ItemsSource="{Binding PersonViewModel.PersonItems}">
    <ListBox.ItemTemplate>
      <DataTemplate DataType="{x:Type PersonModel}">
        <Border>
          <Grid>
            <Grid.RowDefinitions>
              <RowDefinition Height="auto" />
              <RowDefinition Height="auto" />
            </Grid.RowDefinitions>

            <!-- Bind the Command to the nested NavigationViewModel -->
            <RadioButton Content="{Binding Name}"
                         CommandParameter="{Binding}"
                         Command="{Binding NavigationViewModel.ShowPageCommand}"
                         Style="{StaticResource ItemsButtonStyle}" />
          </Grid>
        </Border>
      </DataTemplate>
    </ListBox.ItemTemplate>
  </ListBox>
</UserControl>

PersonModelDetailsView.xaml
The details view.

<UserControl x:Name="Root">
  <ContentControl Content="{Binding ElementName=Root, Path=PersonModel}"
                  ContentTemplate="{Binding ElementName=Root, Path=PersonModelTemplate}" />
</UserControl>

PersonModelDetailsView.xaml.cs

partial class PersonModelDetailsView : UserControl
{
  public PersonModel PersonModel
  {
    get => (PersonModel)GetValue(PersonModelProperty);
    set => SetValue(PersonModelProperty, value);
  }

  public static readonly DependencyProperty PersonModelProperty = DependencyProperty.Register(
    nameof(PersonModel),
    typeof(PersonModel),
    typeof(PersonModelDetailsView),
    new FrameworkPropertyMetadata(default));

  public DataTemplate PersonModelTemplate
  {
    get => (DataTemplate)GetValue(PersonModelTemplateProperty);
    set => SetValue(PersonModelTemplateProperty, value);
  }

  public static readonly DependencyProperty PersonModelTemplateProperty = DependencyProperty.Register(
    nameof(PersonModelTemplate),
    typeof(DataTemplate),
    typeof(PersonModelDetailsView),
    new FrameworkPropertyMetadata(default));
}

MainWindow.xaml

<Window>
  <Window.DataContext>
    <MainViewModel />
  </Window.DataContext>

  <Window.Resources>
    <DataTemplate x:Key="PersonModelDetailsViewTemplate" 
                  DataType="{x:Type PersonModel}">
      <Border Width="600"
              MaxHeight="800">
        <Grid>
          <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
          </Grid.RowDefinitions>

          <TextBlock HorizontalAlignment="Left"
                     Grid.Row="1"
                     Grid.Column="0"
                     Text="Name:" />

          <TextBlock HorizontalAlignment="Right"
                     Grid.Row="1"
                     Grid.Column="0"
                     Text="{Binding Name}" />

          <TextBlock HorizontalAlignment="Left"
                     Grid.Row="2"
                     Text="Surname :" />

          <TextBlock HorizontalAlignment="Right"
                     Grid.Row="2"
                     Text="{Binding Surname}" />
        </Grid>
      </Border>
    </DataTemplate>
  </Window.Resources>

  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" /> <!-- Master view -->
      <ColumnDefinition /> <!-- Details view -->
    <Grid.ColumnDefinitions>
  
    <MainUserControl Grid.Column="0" />
    <PersonModelDetailsView Grid.Column="1"
                            PersonModel="{Binding NavigationViewModel.SelectedPersonModel}"
                            PersonModelTemplate="{StaticResource PersonModelDetailsViewTemplate}" />
  </Grid>
</Window>

MainWindow.xaml.cs

partial class MainWindow : Window
{
  private readonly MainViewModel MainViewModel;

  public MainWindow()
  {
    this.MainViewModel = new MainViewModel();
    this.DataContext = this.MainViewModel;

    InitializeComponent();

    // Initialize the view model classes
    this.Loaded += OnLoaded;
  }

  private void OnLoaded(object sender, RoutedEventArgs e)
  {
    // Initializing all view models from the loaded event is a significant performnace improvement.
    // Just think about doing all of this work from the constructor 
    // where each view model class instantiates its own classes that 
    // themself create instances from their constructor and initialize 
    // them. It would take "ages" for the construction of the top-level 
    // instance to complete, while the UI remains unresponsive. 
    // You can even call async methods which isn't possible in the 
    // constructor. 
    // Every class must perform expensive/long-running initialization 
    // outside the constructor.
    this.MainViewModel.Initialize();
  }

  // TODO::Implement window close and application close logic.
  // The logic that was originally implemented in the view model class.
  // For example use event handlers or routed events or routed commands.
}

MainViewModel.cs

class MainViewModel : INotifyPropertyChanged
{
  public PersonViewModel PersonViewModel { get; } = new PersonViewModel();
  public NavigationViewModel NavigationViewModel { get; } = new NavigationViewModel();

  // Can be async if required
  public void Initialize()
  {
    // Do not make such potentially long-running and blocking calls from the constructor
    this.PersonViewModel.Initialize();
  }
}

PersonViewModel.cs

class PersonViewModel : ViewModelBase
{
  public ObservableCollection<PersonModel> PersonItems { get; }
    
  // The model class to access the database
  private readonly DataRepository dataRepository;

  public PersonViewModel()
  {
    this.PersonItems = new ObservableCollection<PersonModel>();
  }

  // Can be async if required
  public void Initialize()
  {
    // Do not make such potentially long-running and blocking calls from the constructor
    IEnumerable<PersonModel> personModels = this.dataRepository.GetPersonModels();
    foreach (PersonModel personModel in personModels)
    {
      this.PersonItems.Add(personModel);
    }
  }
}

NavigationViewModel.cs

class NavigationViewModel : INotifyPropertyChanged
{
  public NavigationViewModel()
  {
    // Set Startup Page
    SelectedViewModel = new StartupViewModel();
  }

  public event PropertyChangedEventHandler PropertyChanged;
  private void OnPropertyChanged(string propName) 
    => this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));

  // Select ViewModel
  private object _selectedViewModel;
  public object SelectedViewModel
  {
    get => _selectedViewModel;
    set { _selectedViewModel = value; OnPropertyChanged(nameof(this.SelectedViewModel)); }
  }

  // Selected PersonModel
  private PersonModel _selectedPersonModel;
  public PersonModel SelectedPersonModel
  {
    get => _selectedPersonModel;
    set { _selectedPersonModel = value; OnPropertyChanged(nameof(this.SelectedPersonModel)); }
  }
  public void ExecuteShowPageCommand(object commandParameter)
  {
    if (commandParameter is not PersonModel detailsPersonModel)
    {
      return;
    }

    // Use data models to navigate.
    // Creating controls in the view model class (like you were doing)
    // is forbidden in MVVM!
    this.SelectedPersonModel = detailsPersonModel;
  }

  private ICommand _CrudCommand;
  public ICommand ShowPageCommand
  {
    get
    {
      if (_CrudCommand == null)
      {
        _CrudCommand = new RelayCommand(ExecuteShowPageCommand);
      }
      return _CrudCommand;
    }
  }

  /* 
    * The following code does not belong into a view model class. 
    * This must be handled by the view! For example in code-behind.
    * You can use event handlers for Button.Click events or routed commands.
    * Then close the Window or the application from there.
    * Handling controls in the view model violates the MVVM design pattern.
    */

  //// Close App
  //public void CloseApp(object obj)
  //{
  //  MainWindow win = obj as MainWindow;
  //  win.Close();
  //}

  //// Close App Command
  //private ICommand _closeCommand;
  //public ICommand CloseAppCommand
  //{
  //  get
  //  {
  //    if (_closeCommand == null)
  //    {
  //      _closeCommand = new RelayCommand(p => CloseApp(p));
  //    }
  //    return _closeCommand;
  //  }
  //}
}

DataRepository.cs
The model class.
Data persistence (database and file I/O or service consumption) always belongs to the application model. And not the view model or data model classes. Aim to have all queries in a single place (to avoid duplicate code).

class DataRepository
{
  public IEnumerable<PersonModel> GetPersonModels()
  {
    var persons = new List<PersonModel>();
    var Connect = ConfigurationManager.ConnectionStrings["MysqlConnection"].ConnectionString;
    using (var conn = new MySqlConnection(Connect))
    using (var command = new MySqlCommand())
    {
      conn.Open();
      command.Connection = conn;
      command.CommandText = @"SELECT person.id, person.name, person.surname, person.address, person.age, person.contact department.name AS 'department', group.name AS 'group', eductation.lavel division.name AS 'division' FROM person
        LEFT JOIN department ON department.id = person.departmentID LEFT JOIN group ON group.id = person.groupID LEFT JOIN eductation ON eductation.id = person.eductationLavelID LEFT JOIN division ON division.id = person.divisionID";
      using MySqlDataReader reader = command.ExecuteReader();
      while (reader.Read())
      {
        Person_list.Add(new PersonModel()
        {
          PersonID = (int)reader["id"],
          Name = (string)reader["name"],
          Surname = (string)reader["surname"],
          PersonAge = (int)reader["age"],
          PersonAddress = (string)reader["address"],
          PersonDepartmentID = (string)reader["department"],
          PersonGroupID = (string)reader["group"],
          PersonContact = (string)reader["contact"],
          PersonLevelEductationID = (string)reader["lavel"],
          PersonDivisionID = (string)reader["division"]
        });
      }
    }
  
    // Don't close these IDisposables. The using-block will handle that.
    //reader. Close();
    //conn.Close();

    return persons;
  }
}

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật