【问题标题】:I cant add new data to DataGrid我无法向 DataGrid 添加新数据
【发布时间】:2023-04-01 10:26:02
【问题描述】:

我一直在寻找类似的问题,并在我的代码中进行了很多更改,但我无法解决它。

我已经创建了一个 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>

我使用的类的列表在 Main 模型中。

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

公共 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 位于我使用另一个类和 ContentControl 管理的另一个视图中:

其实我有:

  • MainViewModel 和 MainView。
  • VariablesViewModel 和 VariablesView 我放在 ContentControl 中。 VariablesViewModel 是空的,我只用它来显示 VariablesView。

当我执行命令时,我会在 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>

变量视图模型: 空课。

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();

    }
  }
}

【问题讨论】:

  • 使用 observablecollection 而不是列表。
  • 添加了新项目,但 DataGrid 没有注意到集合已更改。更改 VarDt 属性以引发 PropertyChanged 事件(不推荐)或更好地使用 ObservableCollection,它引发 CollectionChanged 事件以通知 ItemsControl (DataGrid) 有关更改。
  • 阅读备注了解更多:INotifyCollectionChanged
  • 您好,我已经尝试过使用 ObservableCollection 而不是 List,但仍然无法正常工作。还有其他想法吗?

标签: wpf mvvm binding datagrid inotifypropertychanged


【解决方案1】:

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

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

VariablesView.xaml

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

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

结果是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>

【讨论】:

    猜你喜欢
    • 2010-12-18
    • 1970-01-01
    • 2010-10-15
    • 2011-03-29
    • 2014-10-11
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 2014-09-11
    相关资源
    最近更新 更多