如何在不同视图中引用相同的视图模型

时间:2016-03-03 14:12:32

标签: c# wpf xaml mvvm viewmodel

我有一个视图模型,它继承自ParentModel类型的observablecollection类。该视图模型绑定到用户控件中的按钮,单击该按钮时,它将在主窗口的datagrid控件中添加一个新条目。该datagrid也绑定到视图模型,但是当我尝试添加新父级时,没有新的条目/行显示在datagrid中。我的问题是如何从用户控件中的按钮引用相同的视图模型实例到datagrid控件?

以下是示例代码

查看型号:

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}" />

来自mainwindow XAML的Datagrid:

<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

MainWindow 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>

1 个答案:

答案 0 :(得分:1)

我建议不要使用ObservableCollection的DataContext。

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}">

,无需在DataGrid中设置DataContext