Problem with DisplayMemberBinding

Apr 19, 2010 at 1:25 PM

Dear all ,

 

I'm trying to use the WPF Application Framework with Entity Framework and I have a problem.
I have two models: Site and Desk. I renamed the Desk's navigation property attribute to "Sito" which links Desk to Site entity and obviously I have a table Desk with a foreign key id_site (int).

 

I add to EntityService two ObservableCollections:  Sites and DeskTypes.

 

MyProject.Applications.Services

 

public class EntityService : IEntityService

 

  public ObservableCollection<Site> Sites
        {
            get
            {
                if (sites == null && entities != null)
                {
                    IQueryable<Site> myquery = entities.CreateQuery<Site>("[Sites]");
                    sites = new EntityObservableCollection<Site>(entities, "Sites", myquery);
                }
                return sites;
            }
        }
  public ObservableCollection<string> DeskTypes
        {
            get
            {
                if (deskTypes == null && entities != null)
                {
                    deskTypes = new ObservableCollection<string>();
                    deskTypes.Add("A");
                    deskTypes.Add("B");

 

                }
                return deskTypes;
            }
        }

 

 

 

Then I modified the Initialize() of  DeskController  class:

 

public void Initialize()
        {
            deskViewModel.PropertyChanged += DeskViewModelPropertyChanged;

 


            IDeskListView deskListView = container.GetExportedValue<IDeskListView>();
            deskListViewModel = new DeskListViewModel(deskListView, entityService.Desks);
            deskListViewModel.AddNewCommand = addNewCommand;
            deskListViewModel.RemoveCommand = removeCommand;

 

            deskListViewModel.PropertyChanged += DeskListViewModelPropertyChanged;

 

            shellViewModel.DeskListView = deskListViewModel.View;
            shellViewModel.DeskView = deskViewModel.View;

 

            deskViewModel.LoadCombo(entityService.Sites, entityService.DeskTypes);

 

            deskListViewModel.SelectedDesk = deskListViewModel.Desks.FirstOrDefault();
        }

 


I have two combobox on DeskView UseControl: one for "Desk.Sito" and an other for "Desk.Tipo"

 

I created DeskViewModel as following:

 

 

MyProject.Applications.ViewModels.DeskViewModel

 

 

 ....

 

        public IEnumerable<string> TipiPostazione { get { return deskTypes; } }
        public IEnumerable<Site> Siti { get { return sites; } }

 

 
       public void LoadCombo(IEnumerable<Site> _sites, IEnumerable<string> _deskTypes)
        {
            sites = _sites;
            deskTypes = _deskTypes;
        }

 

 

This is my DeskView class:

 

MyProject..Presentation.Views.DeskView.xaml

 

...

 

       <Label Content="{x:Static p:Resources.Sito}" Grid.Column="0" Grid.Row="0"/>
        <ComboBox ItemsSource="{Binding Siti, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=true,
                     ValidatesOnDataErrors=true, NotifyOnValidationError=true}"
                  SelectedItem="{Binding Desk.Sito}" Grid.Column="1" Grid.Row="0">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" >
                        <TextBlock Text="{Binding Path=Nome}" />
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ComboBox>
       
        <Label Content="{x:Static p:Resources.Nome}" Grid.Column="0" Grid.Row="1"/>
        <TextBox  x:Name="nomeBox"  Text="{Binding Desk.Nome, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=true,
                     ValidatesOnDataErrors=true, NotifyOnValidationError=true}"
                 MaxLength="30" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Stretch"/>

 

 

        <Label Content="{x:Static p:Resources.Tipo}" Grid.Column="0" Grid.Row="2"/>
        <ComboBox ItemsSource="{Binding TipiPostazione}"
                  SelectedItem="{Binding Desk.Tipo}" Grid.Column="1" Grid.Row="2">
        </ComboBox>

 

 

 ...

 

an finally the DeskListView view:

 

MyProject..Presentation.Views.DeskListView.xaml

 

 

...

 

    <ListView ItemsSource="{Binding Desks}" SelectedItem="{Binding SelectedDesk}"
                  SelectionChanged="ListViewSelectionChanged" >
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding Sito.Nome}" Header="{x:Static p:Resources.Sito}" Width="100"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Nome}" Header="{x:Static p:Resources.Nome}" Width="125"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Tipo}" Header="{x:Static p:Resources.Tipo}" Width="125"/>
                </GridView>
            </ListView.View>
        </ListView>

When I change the SelectedItem of "TipiPostazione" combobox the  DisplayMemberBinding "Tipo" changes.

 but when I change the SelectedItem of "Siti" combobox Sito.Nome doesn't change. Why?

Any suggestions?

 

 

 

Apr 19, 2010 at 3:37 PM

The problem is one limit of EF...

I found a solution here http://blogs.msdn.com/bethmassi/archive/2009/05/04/notifying-the-ui-when-entity-references-change-in-lookup-comboboxes.aspx

I have to call the appropriate property change notifications in my public partial class Desk.

 public Desk() : base()
        {
             
           this.SitoReference.AssociationChanged +=new CollectionChangeEventHandler(this.Site_AssociationChanged);

            dataErrorSupport = new DataErrorSupport(this)
                .AddValidationRule(Resources.Field_Sito, ValidateSito)
                .AddValidationRule(Resources.Field_Nome, ValidateNome)
                .AddValidationRule(Resources.Field_Tipo, ValidateTipo);
        }

        private void Site_AssociationChanged(object sender,  CollectionChangeEventArgs e ) {
            if (e.Action.Equals(CollectionChangeAction.Remove)) {
                OnPropertyChanging("Sito");
              
            } else {
                OnPropertyChanged("Sito");
            }
        }:

 

and it works!!!!

 

Thanks Beth Massi

Coordinator
Apr 20, 2010 at 6:27 PM

Hi moriald,

Thanks a lot for your feedback. I’m using a very similar approach in the Book entity (BookLibrary.Domain):

public partial class Book : IDataErrorInfo, IFormattable
{
    public Book()
    {
        ...
        LendToReference.AssociationChanged += LendToReferenceAssociationChanged;
    }
    ...
    
    private void LendToReferenceAssociationChanged(object sender, CollectionChangeEventArgs e)
    {
        // The navigation property LendTo doesn't support the PropertyChanged event. We have to raise it ourselves.
        OnPropertyChanged("LendTo");
    }
}

I have opened a bug at Mircosoft connect: https://connect.microsoft.com/VisualStudio/feedback/details/532257/entity-framework-navigation-properties-don-t-raise-the-propertychanged-event

Maybe someone might vote the bug to become more important for Microsoft.