Problems with RegionMemberLifetime

Dec 21, 2010 at 6:32 PM

hi guys,

I´m having problems with the RegionMamberLifeTime. I am using Navigation Service to acess my views, and my view implements the INavigationAware.

When i go to the View 1, it loads some data and how in the Grid, when i go to the View 2, my app do the same thing and show another kind of data.

The problem is, when i go back to my View 1, before i load the data, its shows the old that, an them load the new data and show.

The problem is that the views are not "Destroyed" when i nevigate to another view, what i am doing wrong?

Thats my view Code:

  [Export("AcoesGrid")]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    [RegionMemberLifetime(KeepAlive = false)]
    public partial class AcoesGrid : UserControl, INavigationAware
    {

     .....

       #region INavigationAware Members

        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }

        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
            ViewModel = null;
            var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
            var mainRegion = regionManager.Regions[RegionNames.MainContentRegion];
            mainRegion.Deactivate(this);
        }

        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            ViewModel.LoadData();
        }

        #endregion
    }

 

 

Dec 22, 2010 at 11:19 AM

Could you be more clear about the issue by providing more information like

  • what kind of region you are using
  • Is your views not getting recreated each time you navigate to it?

Also from above why do you want to use a ServiceLocator to get the RegionManager? You can inject into your views constructor like this

private readOnly IRegionManager _regionManager;

[ImportingConstructor]
public AcoesGrid(IRegionManager regionManager)
{
   _regionManager = regionManager;
}

 

 

Dec 22, 2010 at 11:53 AM

hi, thx for reply

1 - what kind of region you are using

 <!--Region3: Main content -->
                                <Border x:Name="ContentBorder" Style="{StaticResource ContentBorderStyle}" Background="White" MinHeight="200">
                                    <ContentControl regions:RegionManager.RegionName="MainContentRegion" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" />
                                </Border>
        // Navigation menu Action
        private void AgMenuAcoes_Click(object sender, EventArgs e)
        {
            RegionManager.RequestNavigate(RegionNames.MainContentRegion, new Uri("AcoesGrid", UriKind.Relative), (callback) => { });
        }
2- Is your views not getting recreated each time you navigate to it?
   No, i put a Breakpoint on the constructor, and its not recreating the views.
3 - I ll will change the ServiceLocator later.
Any other information?
Dec 22, 2010 at 12:37 PM
Edited Dec 22, 2010 at 3:44 PM
Looks like you are trying to navigate to the same view when a view is already loaded. Just in case could check what you see in the ActiveViews collection of the regionmanager when you navigate away?

 


From: lucianotcorreia <notifications@codeplex.com>
To: Shivshankar, Ganesh (IT/IN)
Sent: Wed Dec 22 17:23:32 2010
Subject: Re: Problems with RegionMemberLifetime [CompositeWPF:239142]

From: lucianotcorreia

hi, thx for reply

1 - what kind of region you are using

 <!--Region3: Main content -->
                                <Border x:Name="ContentBorder" Style="{StaticResource ContentBorderStyle}" Background="White" MinHeight="200">
                                    <ContentControl regions:RegionManager.RegionName="MainContentRegion" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" />
                                </Border>
        // Navigation menu Action
        private void AgMenuAcoes_Click(object sender, EventArgs e)
        {
            RegionManager.RequestNavigate(RegionNames.MainContentRegion, new Uri("AcoesGrid", UriKind.Relative), (callback) => { });
        }
2- Is your views not getting recreated each time you navigate to it?
   No, i put a Breakpoint on the constructor, and its not recreating the views.
3 - I ll will change the ServiceLocator later.
Any other information?
Dec 22, 2010 at 1:26 PM
Edited Dec 22, 2010 at 1:35 PM

I think you didnt understand the problem....

when i put  [RegionMemberLifetime(KeepAlive = false)] in a view, its supose to destroy the view when i navigate to another view.

When i go to the View1 and them navigate to the View2, the view 1 need to be destroyed, and if i go back to the View1, it need to be recreated. Thats the problem. The view are no destroyed when i navigate to another view.

 

 

Dec 22, 2010 at 1:32 PM
Edited Dec 22, 2010 at 3:45 PM
You are right. When we set keepalive as false it deactivates and removes the view from the region. What you are doing in the onnavigatedfrom is actually not needed I guess.

I have similar setup but it works for me. I'm sure there something very trivial. Can you post your code and send me a link. I'll have a look at it on my end as well.

 


From: lucianotcorreia <notifications@codeplex.com>
To: Shivshankar, Ganesh (IT/IN)
Sent: Wed Dec 22 18:56:40 2010
Subject: Re: Problems with RegionMemberLifetime [CompositeWPF:239142]

From: lucianotcorreia

I think i didnt understand the problem....

when i put [RegionMemberLifetime(KeepAlive = false)] in a view, its supose to destroy the view when i navigate to another view.

When i go to the View1 and them navigate to the View2, the view 1 need to be destroyed, and if i go back to the View1, it need to be recreated. Thats the problem. The view are no destroyed when i navigate to another view.

 

 

Dec 22, 2010 at 1:55 PM

My aap its a kind of big, and acess data from 3 or 4 wcf Services, i think i cant provide a working sample, but the main code i have posted.

And about the code in the OnNavigatedFrom, i think i dont need that too, but i just try that because its not working.

 

 

 

Dec 22, 2010 at 2:02 PM
Edited Dec 22, 2010 at 3:46 PM
What I would do is just comment out the bits calling your services and look at it step by step.

 


From: lucianotcorreia <notifications@codeplex.com>
To: Shivshankar, Ganesh (IT/IN)
Sent: Wed Dec 22 19:25:40 2010
Subject: Re: Problems with RegionMemberLifetime [CompositeWPF:239142]

From: lucianotcorreia

My aap its a kind of big, and acess data from 3 or 4 wcf Services, i think i cant provide a working sample, but the main code i have posted.

And about the code in the OnNavigatedFrom, i think i dont need that too, but i just try that because its not working.

 

 

 

Dec 22, 2010 at 2:27 PM

i will post my view and view models code:

I think its a prism bug, because its very simples,

1 - my view model:

namespace Art.Solution.Module.Shared.ViewModels
{
    [Export]
    [PartCreationPolicy(CreationPolicy.Shared)]
    [RegionMemberLifetime(KeepAlive = false)]
    public class AcoesViewModel : ViewModelBase<Acao>
    {
        private HeaderGridControl _headerGrid;

        [ImportingConstructor]
        public AcoesViewModel(IDataService dataService, IRegionManager regionManager)
            : base(dataService, regionManager)
        {

            this.ScreenDescriptionSingular = "Ação";
            this.ScreenDescriptionPlural = "Ações";
            this.EditViewName = "AcoesEdit";

            InitializePermissions("Acoes");
        }

        public HeaderGridControl GetHeaderGrid()
        {
            if (_headerGrid != null)
            {
                _headerGrid = null;
            }

            _headerGrid = new HeaderGridControl();
            _headerGrid.Initialize(this, AddCommand, EditCommand, DeleteCommand, new List<string>() { "Descrição" }, SearchCommand, ClearSearchCommand);

            return _headerGrid;
        }

        public override void AddEntity(Acao entity)
        {
            entity.SetEntityDefaults(Helpers.Instance.LoginInfoInstance.GetAuthenticatedUser().UsuarioId,
                Convert.ToInt32(WebContext.Current.User.EmpresaId));

            _dataService.Context.Acaos.Add(entity);
        }

        public override void DeleteEntity(Acao entity)
        {
            if (entity.CanDeleteFixo())
            {
                _dataService.Context.Acaos.Remove(entity);
            }
        }

        public override EntityQuery<Acao> OrderBy(System.ServiceModel.DomainServices.Client.EntityQuery<Acao> query, bool isFirst, string propertyName, bool descending)
        {
            Expression<Func<Acao, object>> sortExpression;

            switch (propertyName)
            {
                case "Descrição":
                    sortExpression = Acao => Acao.Descricao;
                    break;
                default:
                    sortExpression = Acao => Acao.Descricao;
                    break;
            }

            if (isFirst)
            {
                if (descending)
                    return query.OrderByDescending(sortExpression);
                return query.OrderBy(sortExpression);
            }
            else
            {
                if (!descending)
                    return query.ThenByDescending(sortExpression);
                return query.ThenBy(sortExpression);
            }
        }

        public override Expression<Func<Acao, bool>> BuildWhere(string textFilterField, string textFilter)
        {
            Expression<Func<Acao, bool>> whereExpression;

            switch (textFilterField)
            {
                case "Descrição":
                    whereExpression = Acao => Acao.Descricao.Contains(textFilter);
                    break;
                default:
                    whereExpression = Acao => Acao.Descricao.Contains(textFilter);
                    break;
            }

            return whereExpression;
        }

        public override void LoadData()
        {
            IsLoading = true;

            var query = _dataService.Context.GetAcoesQuery();

            if (!string.IsNullOrEmpty(TextFilter))
            {
                query = query.Where(BuildWhere(TextFilterField, TextFilter));
            }

            if (Entities.SortDescriptions.Any())
            {
                bool isFirst = true;
                foreach (SortDescription sd in Entities.SortDescriptions)
                {
                    query = OrderBy(query, isFirst, sd.PropertyName, sd.Direction == ListSortDirection.Descending);
                    isFirst = false;
                }
            }
            else
            {
                query = query.OrderBy(Acao => Acao.Descricao);
            }

            if (PageSize > 0)
            {
                query = query.Skip(PageSize * Entities.PageIndex);
                query = query.Take(PageSize);
            }

            if (_entitiesView.PageSize > 0)
            {
                query = query.Skip(_entitiesView.PageSize * _entitiesView.PageIndex);
                query = query.Take(_entitiesView.PageSize);
            }

            query.IncludeTotalCount = true;

            _dataService.Context.Load(query,
                                     (AcoesLoadOpe) =>
                                     {
                                         if (AcoesLoadOpe.HasError)
                                         {
                                             // Todo: Mostrar erro numa tela padrão
                                             MessageBox.Show(AcoesLoadOpe.Error.ToString());
                                             return;
                                         }

                                         _entities.Clear();
                                         foreach (var entity in AcoesLoadOpe.Entities)
                                         {
                                             _entities.Add(entity);
                                         }

                                         _entitiesView.MoveCurrentToFirst();

                                         _entitiesView.TotalItemCount = AcoesLoadOpe.TotalEntityCount;
                                         _entitiesView.ItemCount = AcoesLoadOpe.TotalEntityCount;

                                         IsLoading = false;
                                     }, null);
        }

        public override void AddCommand(object sender, EventArgs e)
        {
            IsNew = true;
            CurrentItem = null;
            CurrentItem = new Acao();
            ShowEditWindow(typeof(IAcoesEditWindow), EditViewName);
        }

        public override void EditCommand(object sender, EventArgs e)
        {
            IsNew = false;
            CurrentItem = SelectedEntity;

            ShowEditWindow(typeof(IAcoesEditWindow), EditViewName);
        }

        public override void DeleteCommand(object sender, EventArgs e)
        {
            MessageBoxDialog.Show("Deseja realmente excluir o item selecionado?",
                "Excluir item",
                MessageBoxDialogButtons.YesNo,
                MessageBoxDialogIcons.Confirm,
                (s, a) =>
                {
                    IsLoading = true;
                    MessageBoxDialog messageBox = (s as MessageBoxDialog);
                    if (messageBox != null)
                    {
                        if (messageBox.MBResult == MessageBoxResult.Yes)
                        {
                            DeleteEntity(SelectedEntity);
                            SubmitChanges();
                            Entities.Remove(SelectedEntity);
                        }
                        else
                        {
                            IsLoading = false;
                        }
                    }
                });
        }

        public override void SearchCommand(object sender, EventArgs e)
        {
            TextFilterField = _headerGrid.FieldsSearchComboBox.SelectedItem.ToString();
            TextFilter = _headerGrid.SearchTextBox.Text;
        }

        public override void ClearSearchCommand(object sender, EventArgs e)
        {
            TextFilter = string.Empty;
        }

        public override void SaveCommand()
        {
            IsLoading = true;

            if (IsNew)
            {
                AddEntity(CurrentItem);
            }

            Entities.AddNewItem(CurrentItem);
            SelectedEntity = CurrentItem;
            SubmitChanges();

            CloseEditWindow(EditViewName);
        }

        public override void CancelCommand()
        {
            CloseEditWindow(EditViewName);
            RejectChanges();
        }
    }
}

2 - My View

namespace Art.Solution.Module.Shared.Views.Grid
{
    [Export("AcoesGrid")]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    [RegionMemberLifetime(KeepAlive = false)]
    public partial class AcoesGrid : UserControl, INavigationAware
    {
        public AcoesGrid()
        {
            InitializeComponent();
            this.Loaded += (s, args) =>
            {
                HeaderPanel.Children.Clear();
                HeaderPanel.Children.Add(ViewModel.GetHeaderGrid());
            };
        }

        [Import]
        public AcoesViewModel ViewModel
        {
            get
            {
                return (AcoesViewModel)this.DataContext;
            }
            set
            {
                DataContext = value;
            }
        }

        private void DataGridDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (ViewModel.CanUpdate)
            {
                ViewModel.EditCommand(sender, EventArgs.Empty);
            }
            else
            {
                MessageBoxDialog.Show(Helpers.Messages.NO_UPDATE_PERMISSION, string.Format("Art Solution | {0}", this.ViewModel.ScreenDescriptionPlural), MessageBoxDialogButtons.OK, MessageBoxDialogIcons.Warning, null);
            }
        }

        #region INavigationAware Members

        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }

        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
            DataContext = null;
            ViewModel = null;
            var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
            var mainRegion = regionManager.Regions[RegionNames.MainContentRegion];
            mainRegion.Deactivate(this);
        }

        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            ViewModel.LoadData();
        }

        #endregion
    }
}

 

Dec 22, 2010 at 2:59 PM
Edited Dec 22, 2010 at 3:47 PM
One thing I noticed is you have keepalive on both the viewmodel and view. Try keeping it in viewmodel only.
Dec 22, 2010 at 4:06 PM

Any luck? Did you resolve it? Here is a sample project making use of the prism navigation framework and it toggles betwee 2 views. Hope this gives you some lead.

Here whenever you navigate away/to a module it will log the events. Note the created messages in red. It gets logged everytime you navigate to a view from elsewhere.

Cheers!

Dec 22, 2010 at 5:14 PM

I keepalive only the view model and it didnt work,

so i Keepalive only the view, and now i have a new problem.

I set a breakpoint in the view constructor, when i navegate to the view, its fire the breakpoint, all the time i navigate to the view.

Apparentily it was working, but when i removed the breakpoint, and run the application, when i navigate to the view he fire the constructor (so its recreating the view)

but on the screen i sse the data before the "LoadData" event, so, re is passsing again in the constructor but the view is alredy there in the region. I realy dont know what to test now.

Dec 22, 2010 at 6:02 PM

Found the problem:

The view Model cant be

[PartCreationPolicy(CreationPolicy.Shared)]
it need to be 
[PartCreationPolicy(CreationPolicy.NonShared)]
All working now


 

Developer
Dec 22, 2010 at 6:10 PM
Edited Dec 22, 2010 at 6:11 PM

Hi Luciano,

I'm glad that you've found the solution to your issue. Thank you for sharing your findings with the rest of the community, since other users might benefit from reading this. Also, thank you Ganesh for your help in troubleshooting the issue.

Guido Leandro Maliandi
http://blogs.southworks.net/gmaliandi

Dec 23, 2010 at 4:40 AM

Hi Luciano,

Told you it might be a very trivial issue. Good that it got resolved now.