Как ссылаться на одну и ту же модель представления в разных представлениях

У меня есть модель представления, которая наследуется от класса observablecollection типа ParentModel. Эта модель представления привязана к кнопке в пользовательском элементе управления, при нажатии на которую будет добавлена ​​новая запись в элементе управления сеткой данных в главном окне. Эта сетка данных также привязана к модели представления, но когда я пытаюсь добавить нового родителя, в сетке данных нет новых записей/строк. Мой вопрос: как мне сослаться на один и тот же экземпляр модели представления с кнопки в пользовательском элементе управления на элемент управления сеткой данных?

Вот пример кода

Просмотр модели:

public class ParentViewModel : ObservableCollection<ParentModel>
{

    public void AddParent(ParentModel parentModel)
    {
        Add(parentModel);
    }

}

Кнопка из пользовательского элемента управления XAML:

<Button Grid.Row="9" Grid.Column="1" x:Name="btnAddParent" HorizontalAlignment="Right" Content="Add Parent" Width="98" Background="{x:Null}" Height="25" VerticalAlignment="Top" FontSize="12" FontWeight="Bold" Command="{Binding AddParentCommand, Source={StaticResource parentViewModel}}" CommandParameter="{Binding}" />

Сетка данных из главного окна XAML:

<DataGrid x:Name="dgvParent" Grid.Row="1" HorizontalAlignment="Stretch" Height="Auto" VerticalAlignment="Stretch" Width="Auto" SelectionMode="Single" BorderThickness="2" Style="{StaticResource AzureDataGrid}" AutoGenerateColumns="False" AlternatingRowBackground="LightBlue"  DataContext="{Binding Source={StaticResource parentViewModel}}" ItemsSource="{Binding}" CanUserAddRows="False">
                    <DataGrid.Columns>
                        <DataGridTextColumn Binding="{Binding PId}" FontWeight="Bold" Header="Id" />
                        <DataGridTextColumn Binding="{Binding PLastName}" FontWeight="Bold" Header="Last Name" />
                        <DataGridTextColumn Binding="{Binding PFirstName}" FontWeight="Bold" Header="First Name" />
                        <DataGridTextColumn Binding="{Binding PMiddleName}" FontWeight="Bold" Header="Middle Name" />
                        <DataGridTextColumn Binding="{Binding PAddress}" FontWeight="Bold" Header="Address" />
                        <DataGridTextColumn Binding="{Binding PContactNo}" FontWeight="Bold" Header="Contact Number" />
                        <DataGridTextColumn Binding="{Binding PEmail}" FontWeight="Bold" Header="Email" />
                        <DataGridTextColumn Binding="{Binding PCreatedOn}" FontWeight="Bold" Header="Created On" />
                        <DataGridTextColumn Binding="{Binding PUpdatedAt}" FontWeight="Bold" Header="Updated At" />
                    </DataGrid.Columns>
                </DataGrid>

ИЗМЕНИТЬ:

В моем главном окне есть другая модель представления, привязанная к сетке, эта модель представления используется для того, чтобы сделать пользовательский элемент управления видимым при нажатии кнопки.

MainViewModel:

public class MainViewModel : INotifyPropertyChanged
{
    #region Constructors
    public MainViewModel()
    {
        _showUserControlCommand = new ShowUserControlCommand(ShowUserControl, IsExecutable);
    }
    #endregion

    #region Events
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion

    #region Methods
    public bool IsExecutable(object context)
    {
        return true;
    }
    #endregion

    #region Commands and Properties
    private Visibility _visibility = Visibility.Collapsed;

    public Visibility ChangeControlVisibility
    {
        get { return _visibility; }
        set { _visibility = value; OnPropertyChanged("ChangeControlVisibility"); }
    }

    public void ShowUserControl(object context)
    {
        if (ChangeControlVisibility == Visibility.Collapsed)
        {
            ChangeControlVisibility = Visibility.Visible;
        }
        else
        {
            ChangeControlVisibility = Visibility.Collapsed;
        }
    }

    private ICommand _showUserControlCommand;

    public ICommand ButtonClickCommand
    {
        get { return _showUserControlCommand; }
        set { _showUserControlCommand = value; }
    }
    #endregion

XAML главного окна:

<Controls:MetroWindow x:Class="RegistrationApp.Views.MainWindow"
                  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                  xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
                  xmlns:m="clr-namespace:RegistrationApp.Models"
                  xmlns:vm="clr-namespace:RegistrationApp.ViewModels"
                  xmlns:vw="clr-namespace:RegistrationApp.Views"
                  xmlns:cl="clr-namespace:RegistrationApp.Classes"
                  xmlns:local="clr-namespace:RegistrationApp"
                  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                  xmlns:EntityModels="clr-namespace:RegistrationApp.EntityModels" 
                  mc:Ignorable="d" 
                  Title="MainWindow" 
                  Height="750" 
                  Width="600"
                  MinHeight="600"
                  MinWidth="750">
<Controls:MetroWindow.Resources>
    <m:ParentModel x:Key="parent" />
    <vm:ParentViewModel x:Key="parentViewModel" />
    <vm:MainViewModel x:Key="mainViewModel" />
    <vw:AddParentUserControl x:Key="addParentUserControl" />
</Controls:MetroWindow.Resources>
<Grid DataContext="{StaticResource mainViewModel}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="20px" />
        <ColumnDefinition />
        <ColumnDefinition Width="20px" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="20px" />
        <RowDefinition Height="Auto" />
        <RowDefinition />
        <RowDefinition Height="20px" />
    </Grid.RowDefinitions>
    <Grid Grid.Column="1" Grid.Row="1" Height="Auto" Width="Auto">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Image Grid.Column="0" Source="/Images/Mobiliar.png" MaxHeight="300" Width="Auto" HorizontalAlignment="Stretch" Stretch="Fill" />
    </Grid>
    <Controls:MetroAnimatedTabControl Grid.Row="2" Grid.Column="1" Controls:TabControlHelper.IsUnderlined="True" Controls:TabControlHelper.Transition="Left" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" FontWeight="Bold" FontSize="14">
        <TabItem Header="Parent" Controls:TabControlHelper.Transition="Normal" Margin="0" HorizontalAlignment="Left" Width="110">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <StackPanel Grid.Row="0" Orientation="Horizontal" Height="Auto" Width="Auto" VerticalAlignment="Top" Margin="0,0,0,4">
                    <Button HorizontalAlignment="Stretch" Height="24" Width="Auto" Margin="20,10,0,0" Command="{Binding ButtonClickCommand}" >
                        <StackPanel Orientation="Horizontal">
                            <Image MinHeight="10" MinWidth="10" Source="/Images/add_icon.png" Stretch="UniformToFill" Margin="0,0,2,0" />
                            <TextBlock Text="Add" FontSize="12" />
                        </StackPanel>
                    </Button>
                    <Button HorizontalAlignment="Stretch" Height="24" Width="Auto" Margin="10,10,0,0">
                        <StackPanel Orientation="Horizontal">
                            <Image MinHeight="10" MinWidth="10" Source="/Images/delete_icon.png" Stretch="UniformToFill" Margin="0,0,2,0" />
                            <TextBlock Text="Delete" FontSize="12" />
                        </StackPanel>
                    </Button>
                    <Button HorizontalAlignment="Stretch" Height="24" Width="Auto" Margin="10,10,0,0">
                        <StackPanel Orientation="Horizontal">
                            <Image MinHeight="10" MinWidth="10" Source="/Images/edit_icon.png" Stretch="UniformToFill" Margin="0,0,2,0" />
                            <TextBlock Text="Edit" FontSize="12" />
                        </StackPanel>
                    </Button>
                </StackPanel>
                <DataGrid x:Name="dgvParent" Grid.Row="1" HorizontalAlignment="Stretch" Height="Auto" VerticalAlignment="Stretch" Width="Auto" SelectionMode="Single" BorderThickness="2" Style="{StaticResource AzureDataGrid}" AutoGenerateColumns="False" AlternatingRowBackground="LightBlue"  DataContext="{Binding Source={StaticResource parentViewModel}}" ItemsSource="{Binding}" CanUserAddRows="False">
                    <DataGrid.Columns>
                        <DataGridTextColumn Binding="{Binding PId}" FontWeight="Bold" Header="Id" />
                        <DataGridTextColumn Binding="{Binding PLastName}" FontWeight="Bold" Header="Last Name" />
                        <DataGridTextColumn Binding="{Binding PFirstName}" FontWeight="Bold" Header="First Name" />
                        <DataGridTextColumn Binding="{Binding PMiddleName}" FontWeight="Bold" Header="Middle Name" />
                        <DataGridTextColumn Binding="{Binding PAddress}" FontWeight="Bold" Header="Address" />
                        <DataGridTextColumn Binding="{Binding PContactNo}" FontWeight="Bold" Header="Contact Number" />
                        <DataGridTextColumn Binding="{Binding PEmail}" FontWeight="Bold" Header="Email" />
                        <DataGridTextColumn Binding="{Binding PCreatedOn}" FontWeight="Bold" Header="Created On" />
                        <DataGridTextColumn Binding="{Binding PUpdatedAt}" FontWeight="Bold" Header="Updated At" />
                    </DataGrid.Columns>
                </DataGrid>
            </Grid>

person Gab    schedule 03.03.2016    source источник


Ответы (1)


Я советую не использовать DataContext, который является ObservableCollection.

WPF Window ссылается на экземпляр ViewModel. В этой ViewModel вместо этого поместите свойство, которое является ObservableCollection

public class MyViewModel
{
    private ObservableCollection<ParentModel> _myItems = new ObservableCollection<ParentModel>();

    public ObservableCollection<ParentModel> MyItems
    {
       get { return _myItems; }
    }

    public void AddParent(ParentModel parentModel)
    {        
        this.MyItems.Add(parentModel);
    }
}

Затем установите для своего Window DataContext экземпляр MyViewModel. Хотя это и не лучшая практика, вы можете установить его в коде окна в конструкторе

/* window constructor */
public MyWindow()
{
   this.DataContext = new MyViewModel();
}

И, наконец, в вашем XAML

<DataGrid ... ItemsSource="{Binding MyItems}">

и нет необходимости задавать DataContext в DataGrid

person Luis Filipe    schedule 03.03.2016
comment
О, я забыл упомянуть, что есть еще одна модель представления, которая привязана к сетке главного окна, эта модель представления используется для того, чтобы сделать пользовательский элемент управления видимым при нажатии кнопки. Я отредактирую свой вопрос. - person Gab; 03.03.2016