ListView selection updates a textbox in other region

Topics: Prism v2 - WPF 3.5
Nov 8, 2009 at 5:57 AM


In order to learn more about Prism I developed this simple project: I have a shell with 2 regions.

Region A contains a module with a view with a ListView. Region B contains the same module with another view with a textbox.

I want that when I click on any item in the ListView the text is shown in the TextBox in region B. That simple.

Both views have their own model classes. I used event aggregators to communicate both views.

I followed Brian Genisio's List Commanding classes and it works great: clicking on the ListView publishes an event that is consumed by the model of region B.

By setting a setting a breakpoint in the model of the view assigned to region B I can see that the information from region A was sent correctly.

However the textbox in module B does not update and is not showing the data from the selected item. Please help me with this problem.

Here's the main code of the model assigned to the view of module B:

public class ItemsDetailsModel: IItemsDetailsModel, INotifyPropertyChanged
        public businessEntities.categoriesEntities selectedCategory = new businessEntities.categoriesEntities();
        public businessEntities.categoriesEntities SelectedCategory
            get { return selectedCategory; } 
                this.selectedCategory = value;

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string propertyName)
            PropertyChangedEventHandler propertyChanged = PropertyChanged;
            if (propertyChanged != null)
                propertyChanged(this, new PropertyChangedEventArgs(propertyName));

        private Views.IItemDetails detailsView;
        public Views.IItemDetails DetailsView
            get { return this.detailsView; }
            set { this.detailsView = value; }
        } // ListView

        public ItemsDetailsModel(Views.IItemDetails pv, IEventAggregator pea)
            this.DetailsView = pv;
            this.DetailsView.Model = this;
        } // ItemsDetailsModel(IEventAggregator pea)

        public void WhenItemSelected(PTTInfrastructure.SelectedItem psi)
        // Here, the psi comes from module A with the correct information of the selected item.
            this.SelectedCategory.category =;
            this.SelectedCategory.title1 = psi.text;
        } // WhenItemSelected        
    } // ItemsDetailsModel

This is the simple code of the view for region B

<UserControl x:Class="categoriesModule.Views.ItemDetails"
    Height="300" Width="300">
    <Grid DataContext="SelectedCategory" >
        <Label Height="27" Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" HorizontalAlignment="Left" Width="73">Title:</Label>
        <TextBox  Height="23" Margin="91,14,12,0" Name="txtTitle" VerticalAlignment="Top" Text="{Binding Path=title1}" />

And this is the main part of the code behind the view file:

    public partial class ItemDetails : UserControl, IItemDetails
        public ItemDetails()

        public Models.IItemsDetailsModel Model
            get { return this.DataContext as Models.IItemsDetailsModel; }
            set { this.DataContext = value; }

 Finally I registered everything in the main class of the module with this:

public class categoriesModule : IModule
        public IUnityContainer _mainContainer;
        public IRegionManager _regionManager;

        public categoriesModule(IUnityContainer pc, IRegionManager prm)
            this._mainContainer = pc;
            this._regionManager = prm;
        } // categoriesModule()

        public void Initialize()
            this.registerViewsAndServices(); // This will create instances on the models and views

            Models.IItemsPresentationModel lipm = this._mainContainer.Resolve<Models.IItemsPresentationModel>();
            Models.IItemsDetailsModel lidm = this._mainContainer.Resolve<Models.IItemsDetailsModel>();
            // this._regionManager.RegisterViewWithRegion("regionList", () => this._mainContainer.Resolve<Models.IItemsPresentationModel>().ListView);
        } // Initialize

        public void registerViewsAndServices()
        // We will create instances on the models and views by registering implementators in the container
            this._mainContainer.RegisterType<Views.IListItemsView, Views.listItemsView>();
            this._mainContainer.RegisterType<Models.IItemsPresentationModel, Models.itemsPresentationModel>();
            this._mainContainer.RegisterType<Views.IItemDetails, Views.ItemDetails>();
            this._mainContainer.RegisterType<Models.IItemsDetailsModel, Models.ItemsDetailsModel>();
        } // registerViewsAndServices

    } // class categoriesModule
I hope somebody can help me.
Nov 8, 2009 at 7:10 AM

Hey ctellez69,

Try changing the line in your ItemsDetailsModel constructor from this:


to this:

pea.GetEvent<PTTInfrastructure.SelectedItemEvent>().Subscribe(WhenItemSelected, ThreadOption.UIThread, true);

I haven't reproduced your code, but it seems like it's not hanging onto the event reference from the Event Aggregator (that's what the true does). And it's always good practice to specify the UI thread if you're going to be updating the UI.



Nov 9, 2009 at 3:34 AM

Hi Ryan,

Unfortunately the code does not work.

Any other idea?

Nov 9, 2009 at 7:30 AM

We can't tell from your code here if your "categoriesEntities" also implement INotifyPropertyChanged which they have to do since you're modifying the properties of that object.

Or if that class doesn't implement INotifyPropertyChanged, you could simple add the following line after updating the properties:
which will trigger an update of the UI.


Nov 10, 2009 at 4:52 AM

Thank you for your response.

"categoriesEntities" is just a simple class and no, it does not implement INotifyPropertyChanged. It is just a plain class with basic info.

I put the "RaisePropertyChanged("SelectedCategory");" at the end of the method "public void WhenItemSelected(PTTInfrastructure.SelectedItem psi)". While debbuging I noticed that inside the "RaisePropertyChanged" method, the "PropertyChanged" event variable is null:

            PropertyChangedEventHandler propertyChanged = PropertyChanged; // <---It is NULL
            if (propertyChanged != null)
                propertyChanged(this, new PropertyChangedEventArgs(propertyName)); // <--- It is never executed

Any idea of this? How can I assign it so it is not null? Am I missing something?

Nov 10, 2009 at 7:34 AM

Ah, sure, missed this the first time I read it... You're setting the DataContext to a string of "SelectedCategory" (<Grid DataContext="SelectedCategory">), change that to:
<Grid DataContext="{Binding SelectedCategory}">, or you could remove that "DataContext=..." and change your TextBox binding to: Text="{Binding SelectedCategory.title1}"

and add the following in your module init:
"lidm.DetailsView.DataContext = lidm;" (At least I couldn't see that you were setting the datacontext of your View anywhere else.)
So that the datacontext of your UserControl is set to your ViewModel.


Nov 11, 2009 at 3:52 AM
Edited Nov 11, 2009 at 3:55 AM

Oh, thank God it finally worked!

Thank you NeoDarque, I eliminated the <Grid DataContext="{Binding SelectedCategory}"> and went directly to binding the textbox:

<TextBox Height="23" Margin="91,14,12,0" Name="txtTitle" VerticalAlignment="Top" Text="{Binding SelectedCategory.title1}" />

That was weird, I always thought that having the DataContext assigned in the Grid or other panel would allow me to bind other components with just "{Binding Path=field}". Am I missing something?

On the other hand, there was no need for adding this line to the module initial class:

lidm.DetailsView.DataContext = lidm;

Because in the constructor of the Model I have:

       public ItemsDetailsModel(Views.IItemDetails pv, IEventAggregator pea)
            this.DetailsView = pv;
            this.DetailsView.Model = this; <-------- Here, I'm assigning the model to the view
        } // ItemsDetailsModel(IEventAggregator pea)

I will keep working on this program. Thank you everybody for your help.