问:绑定到 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;
    }
}

谢谢!!