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

本文关键字:视图 引用 模型 | 更新日期: 2023-09-27 18:37:15

我有一个视图模型,它继承自 ParentModel 类型的可观察集合类。该视图模型绑定到用户控件中的一个按钮,单击该按钮时,它将在主窗口的 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}" />

来自主窗口 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>

编辑:

在我的主窗口中,还有另一个绑定到网格的视图模型,该视图模型用于在单击按钮时使用户控件可见。

主视图模型:

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>

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

我的建议是不要使用ObservableCollection的DataContext。

WPF Window引用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