问:绑定到 ObservableCollection<T> 的 C# WPF DataGrid 未更新
Q: C# WPF DataGrid bound to ObservableCollection<T> gets not updated
我目前在我的 C# WPF 应用程序中遇到一个问题,这个问题似乎很容易解决。但是即使看了好几篇Whosebug的帖子,网上的教程,还是无法解决问题。
我有一个 DataGrid,我正在尝试将其绑定到 ObservableCollection。此外,我将 MVVM 模式(至少我正在尝试)与 PRISM 一起使用。
我的问题是,在我向 ObservableCollection 添加新规则后,DataGrid 没有被填充。当我调试我可以看到的应用程序时,该集合包含项目。正如您从代码中看到的那样,我使用 Bindablebase 中的 RaisePropertyChanged 来触发 PropertyChangedEvent。我还将 DataGrid 的 ItemSource 绑定到 RuleList。
有人能看出我做错了什么吗?
提前致谢,
迈克尔
这是我的 RuleModel.cs:
namespace MyApp.GenericViews.Model
{
public class RuleModel
{
public bool IsEnabled { get; set; }
public string RuleName { get; set; }
public string Source { get; set; }
public string Target { get; set; }
public string ModuleName { get; set; }
public string ElementName { get; set; }
public RuleModel()
{
}
}
}
这是我的 View.xaml:
<UserControl
x:Class="MyApp.GenericViews.View.RulesView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyApp.GenericViews.View"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:MyApp.GenericViews.ViewModel"
d:DataContext="{d:DesignInstance d:Type=vm:RulesViewModel}"
d:DesignHeight="600"
d:DesignWidth="800"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Content="{Binding Title}" />
<!--<StackPanel Grid.Row="0" Orientation="Horizontal">
<Button Content="Add" Style="{StaticResource DefaultDialogButton}" />
<Button Content="Remove" Style="{StaticResource DefaultDialogButton}" />
</StackPanel>-->
<DataGrid
Name="RulesDataGrid"
Grid.Row="1"
Margin="5"
AutoGenerateColumns="False"
ItemsSource="{Binding Path=RuleList, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<DataGrid.Columns>
<!--<DataGridCheckBoxColumn Width="40" Binding="{Binding Path=IsEnabled}" />-->
<DataGridTextColumn
Width="100"
Binding="{Binding Path=RuleName, UpdateSourceTrigger=PropertyChanged}"
Header="Name" />
<DataGridTextColumn
Width="100"
Binding="{Binding ModuleName}"
Header="Module" />
<!--<DataGridComboBoxColumn
Width="100"
Header="Element"
ItemsSource="{Binding ModuleList}"
SelectedItemBinding="{Binding Path=ElementName}" />-->
<DataGridTextColumn
Width="50*"
Binding="{Binding Source}"
Header="Source" />
<DataGridTextColumn
Width="50*"
Binding="{Binding Target}"
Header="Target" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
这是我的ViewModel.cs。
namespace MyApp.GenericViews.ViewModel
{
public class RulesViewModel : BindableBase, INavigationAware, IViewModel
{
private XmlDatabase _xmlDatabase;
private readonly IUnityContainer _container;
private readonly IEventAggregator _eventAggregator;
public IMyAppView View { get; set; }
public List<string> ModuleList { get; set; }
private string _title;
public string Title
{
get { return _title; }
set
{
if (_title != value)
{
_title = value;
SetProperty(ref _title, value);
RaisePropertyChanged(nameof(Title));
}
}
}
private Rule _selectedRule;
public Rule SelectedRule
{
get { return _selectedRule; }
set
{
if (_selectedRule != value)
{
SetProperty(ref _selectedRule, value);
RaisePropertyChanged(nameof(SelectedRule));
}
}
}
private ObservableCollection<RuleModel> _RuleList;
public ObservableCollection<RuleModel> RuleList
{
get { return _RuleList; }
set
{
if (_RuleList != value)
{
SetProperty(ref _RuleList, value, nameof(RuleList));
//RaisePropertyChanged(nameof(RuleList));
//OnPropertyChanged(nameof(RuleList));
}
}
}
public RulesViewModel(IRuleView view, IUnityContainer c, IEventAggregator evt)
{
View = view;
View.ViewModel = this;
_container = c;
_eventAggregator = evt;
_eventAggregator.GetEvent<RuleCommand>().Subscribe(DoProcessRuleCommand);
}
private void DoProcessRuleCommand(RuleCommandType commandType)
{
switch (commandType)
{
case RuleCommandType.AddRule:
if (RuleList.IsNullOrEmpty())
{
RuleList = new ObservableCollection<RuleModel>();
}
var newRule = new RuleModel()
{
RuleName = "new rule",
};
RuleList.Add(newRule);
RaisePropertyChanged(nameof(RuleList));
//OnPropertyChanged(nameof(RuleList));
break;
case RuleCommandType.DeleteRule:
if (RuleList.IsNeitherNullNorEmpty())
{
//RuleList.Remove(Selected)
}
break;
default:
break;
}
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
_xmlDatabase = _container?.Resolve<XmlDatabase>();
if (_xmlDatabase != null)
{
RuleList = new ObservableCollection<RuleModel>(_xmlDatabase.Rules.Select(r => RuleModel.FromSerializable(r)));
}
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
}
}
好的,在 Ivoros 在评论中提示我检查 UserControl 的 DataContext 之后,我查看了 View.xaml.cs 背后的代码。
原来我忘了 return public 视图上的 DataContext 属性
之前:
public IMiCasaViewModel ViewModel { get; set; }
之后:
public IMiCasaViewModel ViewModel
{
get
{
return (INormalizationViewModel)DataContext;
}
set
{
DataContext = value;
}
}
谢谢!!
我目前在我的 C# WPF 应用程序中遇到一个问题,这个问题似乎很容易解决。但是即使看了好几篇Whosebug的帖子,网上的教程,还是无法解决问题。
我有一个 DataGrid,我正在尝试将其绑定到 ObservableCollection。此外,我将 MVVM 模式(至少我正在尝试)与 PRISM 一起使用。
我的问题是,在我向 ObservableCollection 添加新规则后,DataGrid 没有被填充。当我调试我可以看到的应用程序时,该集合包含项目。正如您从代码中看到的那样,我使用 Bindablebase 中的 RaisePropertyChanged 来触发 PropertyChangedEvent。我还将 DataGrid 的 ItemSource 绑定到 RuleList。
有人能看出我做错了什么吗?
提前致谢,
迈克尔
这是我的 RuleModel.cs:
namespace MyApp.GenericViews.Model
{
public class RuleModel
{
public bool IsEnabled { get; set; }
public string RuleName { get; set; }
public string Source { get; set; }
public string Target { get; set; }
public string ModuleName { get; set; }
public string ElementName { get; set; }
public RuleModel()
{
}
}
}
这是我的 View.xaml:
<UserControl
x:Class="MyApp.GenericViews.View.RulesView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyApp.GenericViews.View"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:MyApp.GenericViews.ViewModel"
d:DataContext="{d:DesignInstance d:Type=vm:RulesViewModel}"
d:DesignHeight="600"
d:DesignWidth="800"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Content="{Binding Title}" />
<!--<StackPanel Grid.Row="0" Orientation="Horizontal">
<Button Content="Add" Style="{StaticResource DefaultDialogButton}" />
<Button Content="Remove" Style="{StaticResource DefaultDialogButton}" />
</StackPanel>-->
<DataGrid
Name="RulesDataGrid"
Grid.Row="1"
Margin="5"
AutoGenerateColumns="False"
ItemsSource="{Binding Path=RuleList, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<DataGrid.Columns>
<!--<DataGridCheckBoxColumn Width="40" Binding="{Binding Path=IsEnabled}" />-->
<DataGridTextColumn
Width="100"
Binding="{Binding Path=RuleName, UpdateSourceTrigger=PropertyChanged}"
Header="Name" />
<DataGridTextColumn
Width="100"
Binding="{Binding ModuleName}"
Header="Module" />
<!--<DataGridComboBoxColumn
Width="100"
Header="Element"
ItemsSource="{Binding ModuleList}"
SelectedItemBinding="{Binding Path=ElementName}" />-->
<DataGridTextColumn
Width="50*"
Binding="{Binding Source}"
Header="Source" />
<DataGridTextColumn
Width="50*"
Binding="{Binding Target}"
Header="Target" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
这是我的ViewModel.cs。
namespace MyApp.GenericViews.ViewModel
{
public class RulesViewModel : BindableBase, INavigationAware, IViewModel
{
private XmlDatabase _xmlDatabase;
private readonly IUnityContainer _container;
private readonly IEventAggregator _eventAggregator;
public IMyAppView View { get; set; }
public List<string> ModuleList { get; set; }
private string _title;
public string Title
{
get { return _title; }
set
{
if (_title != value)
{
_title = value;
SetProperty(ref _title, value);
RaisePropertyChanged(nameof(Title));
}
}
}
private Rule _selectedRule;
public Rule SelectedRule
{
get { return _selectedRule; }
set
{
if (_selectedRule != value)
{
SetProperty(ref _selectedRule, value);
RaisePropertyChanged(nameof(SelectedRule));
}
}
}
private ObservableCollection<RuleModel> _RuleList;
public ObservableCollection<RuleModel> RuleList
{
get { return _RuleList; }
set
{
if (_RuleList != value)
{
SetProperty(ref _RuleList, value, nameof(RuleList));
//RaisePropertyChanged(nameof(RuleList));
//OnPropertyChanged(nameof(RuleList));
}
}
}
public RulesViewModel(IRuleView view, IUnityContainer c, IEventAggregator evt)
{
View = view;
View.ViewModel = this;
_container = c;
_eventAggregator = evt;
_eventAggregator.GetEvent<RuleCommand>().Subscribe(DoProcessRuleCommand);
}
private void DoProcessRuleCommand(RuleCommandType commandType)
{
switch (commandType)
{
case RuleCommandType.AddRule:
if (RuleList.IsNullOrEmpty())
{
RuleList = new ObservableCollection<RuleModel>();
}
var newRule = new RuleModel()
{
RuleName = "new rule",
};
RuleList.Add(newRule);
RaisePropertyChanged(nameof(RuleList));
//OnPropertyChanged(nameof(RuleList));
break;
case RuleCommandType.DeleteRule:
if (RuleList.IsNeitherNullNorEmpty())
{
//RuleList.Remove(Selected)
}
break;
default:
break;
}
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
_xmlDatabase = _container?.Resolve<XmlDatabase>();
if (_xmlDatabase != null)
{
RuleList = new ObservableCollection<RuleModel>(_xmlDatabase.Rules.Select(r => RuleModel.FromSerializable(r)));
}
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
}
}
好的,在 Ivoros 在评论中提示我检查 UserControl 的 DataContext 之后,我查看了 View.xaml.cs 背后的代码。
原来我忘了 return public 视图上的 DataContext 属性
之前:
public IMiCasaViewModel ViewModel { get; set; }
之后:
public IMiCasaViewModel ViewModel
{
get
{
return (INormalizationViewModel)DataContext;
}
set
{
DataContext = value;
}
}
谢谢!!