简体   繁体   中英

Q: C# WPF DataGrid bound to ObservableCollection<T> gets not updated

I'm currently facing an issue in my C# WPF application, that is seemingly simple to solve. But even after reading several Stackoverflow posts, tutorials on the web i still cannot solve the problem.

I have a DataGrid, that i'm trying to bind to a ObservableCollection. Furthermore, i am using the MVVM pattern (at least i'm trying) together with PRISM.

My Problem is, that the DataGrid does not get populated after i add a new Rule to the ObservableCollection. When i'm debugging the application i can see, that the collection has items contained. As you can see from the code i am using RaisePropertyChanged from the Bindablebase to fire the PropertyChangedEvent. I have also bound the DataGrid's ItemSource to RuleList.

Can anybody see what i'm doing wrong?

Thanks in Advance,

Michael

Here is my 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()
        {

        }

    }
}

Here is my 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>

Here is my 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)
        {

        }
    }
}

Ok, after Ivoros gave me the hint in the comments to review the UserControl's DataContext i looked into the code behind of my View.xaml.cs.

It turnes out that i forgot to return the DataContext on the public View property

before:

public IMiCasaViewModel ViewModel { get; set; }

after:

public IMiCasaViewModel ViewModel 
{ 
    get
    {
        return (INormalizationViewModel)DataContext;
    }
    set
    {
        DataContext = value;
    }
}

Thank You!!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM