我无法向 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 管理的另一个视图中:
其实我有:
- MainViewModel 和 MainView。
- 我放在 ContentControl 中的 VariablesViewModel 和 VariablesView。
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>
变量视图模型:
空 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();
}
}
}
VariablesView
将 MainViewModel
明确定义为 XAML 中的 DataContext
。这就是 DataGrid
显示初始值的原因:来自 MainViewModel
构造函数的值。由于这是一个新实例,更改一个实例的值不会更改第二个实例的值。
解决此问题的两个简单解决方案。
一种解决方案是将 VariablesView
的 DataContext
绑定到原始 MainViewModel
实例。
您可以定义一个 RelativeSource
来查找父 ContentControl
并使用它的 DataContext
作为 DataContext
绑定的来源:
VariablesView.xaml
<UserControl DataContext="{Binding RelativeSource={RelativeSource AncestorType=ContentControl}, Path=DataContext}">
...
</UserControl>
第二个也是推荐的解决方案是使用继承自 DataTemplate
的自然 DataContext
。
结果是VariablesViewModel
不能为空。如果 MainViewModel
和 VariablesViewModel
共享数据,如 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>
我一直在寻找这样的问题,并在我的代码中做了很多更改,但我无法解决它。
我创建了一个 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 管理的另一个视图中:
其实我有:
- MainViewModel 和 MainView。
- 我放在 ContentControl 中的 VariablesViewModel 和 VariablesView。 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>
变量视图模型: 空 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();
}
}
}
VariablesView
将 MainViewModel
明确定义为 XAML 中的 DataContext
。这就是 DataGrid
显示初始值的原因:来自 MainViewModel
构造函数的值。由于这是一个新实例,更改一个实例的值不会更改第二个实例的值。
解决此问题的两个简单解决方案。
一种解决方案是将 VariablesView
的 DataContext
绑定到原始 MainViewModel
实例。
您可以定义一个 RelativeSource
来查找父 ContentControl
并使用它的 DataContext
作为 DataContext
绑定的来源:
VariablesView.xaml
<UserControl DataContext="{Binding RelativeSource={RelativeSource AncestorType=ContentControl}, Path=DataContext}">
...
</UserControl>
第二个也是推荐的解决方案是使用继承自 DataTemplate
的自然 DataContext
。
结果是VariablesViewModel
不能为空。如果 MainViewModel
和 VariablesViewModel
共享数据,如 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>