我无法向 DataGrid 添加新数据

I cant add new data to DataGrid

我一直在寻找这样的问题,并在我的代码中做了很多更改,但我无法解决它。

我创建了一个 DataGrid:

    <DataGrid Grid.Row="1" ItemsSource="{Binding VarDt}"  AutoGenerateColumns="False" >
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
            <DataGridTextColumn Header="ID" Binding="{Binding Id}"/>
        </DataGrid.Columns>
    </DataGrid>

我使用的 class 列表在主模型中。

    private List<ObjectVariable> _varDt;
    public List<ObjectVariable> VarDt
    {
        get { return _varDt; }
        set 
        { 
            _varDt = value;
            OnPropertyChanged("VarDt");
        }
    }

当我第一次添加数据时它起作用了,我可以在我的 DataGrid 中看到这些值:

        public MainViewModel()
        {
        VarDt = new List<ObjectVariable>()
        {
            new ObjectVariable { Id="9846849", Name="Val1" },
            new ObjectVariable { Id="fregreg", Name="Val2" },
            new ObjectVariable { Id="cd6s8s6", Name="Val3" }
        }; [...]

但是当我在执行命令时添加新项目时(当我双击树项目时),DataGrid 会更新。 (我添加它不起作用的新项目的代码):

    private ICommand _selectItemCommand;
    public ICommand selectItemCommand
    {
        get
        {
            return _selectItemCommand ?? (_selectItemCommand = new RelayCommand(param => this.LoadContent(param)));
        }
    }

    private void LoadContent(object selectedMenuItem)
    {
        // NEW ITEM THAT IS NOT ADDED WHY???
        VarDt.Add(new ObjectVariable { Id = "cw61851cw", Name = "ValPost" });          
    }

我不知道我是否没有正确引发 PropertyChanged 事件以及我该怎么做。

有人可以告诉我如何将数据正确添加到我的 DataGrid。

谢谢!

编辑 1:仍然无法使用可观察集合

声明:

        private ObservableCollection<ObjectVariable> _varDt;
    public ObservableCollection<ObjectVariable> VarDt
    {
        get { return _varDt; }
        set 
        { 
            _varDt = value;
            OnPropertyChanged("VarDt");
        }
    }

Public MainViewModel():

            VarDt = new ObservableCollection<ObjectVariable>()
        {
            new ObjectVariable { Id="9846849", Name="ValuesAtStart1" },
            new ObjectVariable { Id="fregreg", Name="ValuesAtStart2" },
            new ObjectVariable { Id="cd6s8s6", Name="ValuesAtStart3" }
        };

命令:

        private void LoadContent(object selectedMenuItem)
    {

            // NEW ITEM THAT IS NOT ADDED WHY???
            VarDt.Add(new ObjectVariable { Id = "cw61851cw", Name = "ValueInsideCommand" });
    }

结果(未添加来自命令的数据):

Value inside command not added

编辑 2:找到问题但我没有解决方案

我遇到问题的 DataGrid 在我用另一个 class 和一个 ContentControl 管理的另一个视图中:

其实我有:

当我执行命令时,我在 ContentControl 中显示 VariablesView:

        private void LoadContent(object selectedMenuItem)
    {
        TreeItemModel ItemSelected = (TreeItemModel)selectedMenuItem;

        if (ItemSelected.Name == "Object variables")
        {
            // Current view is VariablesView
            CurrentView = VariableVM;

            // NEW ITEM THAT IS NOT ADDED WHY???
            VarDt.Add(new ObjectVariable { Id = "cw61851cw", Name = "ValueInsideCommand" });

        }
            
        else CurrentView = "";
    }

我意识到我在 ContentControl 中显示的 VariablesView 内的 DataGrid 不会更新值,但是如果我将相同的 DataGrid 放在主视图中,值就会更新。

也许问题是“VarDt”在 MainViewModel 中,而不在 VariablesViewModel 中,但我可以显示一些数据,(只有新值没有显示)

测试代码:

                [...]
            <ContentControl Grid.Column="1"
                            Margin="10"
                            Content="{Binding CurrentView}"/>

            <DataGrid Grid.Row="3" Grid.Column="2" ItemsSource="{Binding VarDt}"  AutoGenerateColumns="True" />
            [...]

测试代码结果: DataBinding result using ContentControl os DataGrid in MainView

编辑 3:完整上下文

变量视图:

<UserControl x:Class="AOE.MVVM.View.VariablesView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:viewmodel="clr-namespace:AOE.MVVM.ViewModel"  
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:AOE.MVVM.View"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
<!--Asignación del archivo .cs a esta view-->
<UserControl.DataContext>
    <viewmodel:MainViewModel/>
</UserControl.DataContext>
<Grid>
    <Grid.RowDefinitions >
        <RowDefinition Height="30*" MaxHeight="70"/>
        <RowDefinition Height="100*"/>
        <RowDefinition Height="10*" MaxHeight="30"/>
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="0">
        <Image Source="/Media/Variables.png"
               Height="50"
               Width="50"
               HorizontalAlignment="Left"/>
        <TextBlock Text="Variables"
                   FontFamily="Verdana"
                   Foreground="#007BC0"/>

    </StackPanel>
    <DataGrid Grid.Row="1" ItemsSource="{Binding VarDt}"  AutoGenerateColumns="True" >

    </DataGrid>
</Grid>

变量视图模型: 空 class.

AppXaml:

<Application x:Class="AOE.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:AOE"
         xmlns:viewModel="clr-namespace:AOE.MVVM.ViewModel"
         xmlns:view="clr-namespace:AOE.MVVM.View"
         StartupUri="MainWindow.xaml">
<Application.Resources>
    
    <DataTemplate DataType="{x:Type viewModel:VariablesViewModel}">
        <view:VariablesView/>
    </DataTemplate>

</Application.Resources>

主视图模型:

namespace AOE.MVVM.ViewModel
{
class MainViewModel : ObservableObject
{

    public ObservableCollection<ObjectVariable> VarDt { get; set; }

    //public TreeItemModel ItemSelected { get; set; }

    private ICommand _selectItemCommand;
    public ICommand selectItemCommand
    {
        get
        {
            return _selectItemCommand ?? (_selectItemCommand = new RelayCommand(param => this.LoadContent(param)));
        }
    }

    private void LoadContent(object selectedMenuItem)
    {

        // Current view is VariablesView
        CurrentView = VariableVM;

        // NEW ITEM THAT IS NOT ADDED WHY???
        VarDt.Add(new ObjectVariable { Id = "cw61851cw", Name = "ValueInsideCommand" });

    }

    public VariablesViewModel VariableVM { get; set; }

    private object _currentView;

    public object CurrentView
    {
        get { return _currentView; }
        set
        {
            _currentView = value;
            OnPropertyChanged("CurrentView");
        }
    }

    public MainViewModel()
    {

        MainTree.Add(MainObject);

        VarDt = new ObservableCollection<ObjectVariable>()
        {
            new ObjectVariable { Id="9846849", Name="ValuesAtStart1" },
            new ObjectVariable { Id="fregreg", Name="ValuesAtStart2" },
            new ObjectVariable { Id="cd6s8s6", Name="ValuesAtStart3" }
        };

        VariableVM = new VariablesViewModel();

    }
  }
}

VariablesViewMainViewModel 明确定义为 XAML 中的 DataContext。这就是 DataGrid 显示初始值的原因:来自 MainViewModel 构造函数的值。由于这是一个新实例,更改一个实例的值不会更改第二个实例的值。

解决此问题的两个简单解决方案。
一种解决方案是将 VariablesViewDataContext 绑定到原始 MainViewModel 实例。
您可以定义一个 RelativeSource 来查找父 ContentControl 并使用它的 DataContext 作为 DataContext 绑定的来源:

VariablesView.xaml

<UserControl DataContext="{Binding RelativeSource={RelativeSource AncestorType=ContentControl}, Path=DataContext}">
  ...
</UserControl>

第二个也是推荐的解决方案是使用继承自 DataTemplate 的自然 DataContext

结果是VariablesViewModel不能为空。如果 MainViewModelVariablesViewModel 共享数据,如 VarDt 属性,则不要复制这些属性。而是将依赖于此共享属性的控件显式绑定到 ContentControl (MainViewModel) 的 DataContext。与 VariablesView 相关的其他非共享数据必须移至 VariablesViewModel.

以下示例假定 VariablesView 不是重用控件。不是,如果可重用性很重要,所有内部绑定 必须 引用继承的 DataContext。这意味着必须避免 Binding.RelativeSource 在 UserControl 之外查找源。

VariablesView.xaml

<!-- DataContext is inherited from the DataTemplate and is the VariablesViewModel -->
<UserControl>

  <!-- Bind explicitly to the shared data located in MainViewModel -->
  <DataGrid ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=ContentControl}, Path=DataContext}" />
</UserControl>