Home > database >  ComboBox binding inside Item template with IEnumerable collection
ComboBox binding inside Item template with IEnumerable collection

Time:03-03

I have one class MovieSystem which inherits from AvailableMovies collection.

public class MovieSystem  : IEnumerable<AvailableMovies >, IEnumerable
{
    public AvailableMovies this[int i] { get; }
    public AvailableMovies this[TheatreLocation location] { get; }
    public AvailableMovies [] ReleasedMovies { get; }
 }

TheatreLocation is an enum with values like

public enum TheatreLocation 
{
        Citycentre = 0,
        CityNorth = 1,
        CitySouth = 2,
        CityEast = 3,
        CityWest = 4,
}

AvailableMovies collection is with below properties

public class AvailableMovies 
{
        public AvailableMovies ();
        public int Index { get; }
        public TheatreLocation Location { get; set; }
        public string TheatreID { get; set; }
        public double Ticketprice{ get; }
}

My Xaml code looks like below

<ItemsControl ItemsSource="{Binding MovieSystem  }">            
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                            <ComboBox 
                                      ItemsSource="{Binding Path= ""What should I bind here? ""}"
                                      DisplayMemberPath="{Binding Path = ???}"
                                      SelectedIndex="{Binding Path =Location , Mode=TwoWay, Converter={StaticResource MovieSystemLocationConverter}}">
                            </ComboBox>
                            <ComboBox
                                      ItemsSource="{Binding Path = ???}"
                                      SelectedIndex="{Binding Path=TheatreID , Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                      DisplayMemberPath="{Binding Path= ??}">
                            </ComboBox>
                            <TextBox Grid.Column="3"
                                     Text="{Binding Path= Ticketprice, Mode =TwoWay,StringFormat=F3, NotifyOnValidationError=True}"/>
                                    
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
</ItemsControl>

I have a view model, xaml datacontext is set to this view model.

internal class MovieSystemPanelViewModel
{
        ///tried this collection but not worked.
        public ObservableCollection<LocationViewModel> Locations { get; } = new ObservableCollection<LocationViewModel>();
   
        public MovieSystem MovieSystem { get; }
              
        public MovieSystemPanelViewModel() {}
}

Now my problem is both ComboBox which should display Theatre id and location not displaying due to binding issue. If try to bind that Locations observable collection inside ComboBox itemsource its not allowing, inside items template only AvailableMovies properties are in bindable condition. Ticketprice is binding properly and displaying.

CodePudding user response:

The issue here is since you are binding Items.Control with a collection, child elements of that Items.Control will have access to that collection's property only. So, if you want to use another collection you need to use relative source to get access in datacontext level. And since it's an enum to properly display, you need to display the dictionary values using an extension method and also using another Itemtemplate inside ComboBox to get the proper display.

internal class MovieSystemPanelViewModel
{
        ///Use  dictionary instead of observable collection
        public Dictionary<TheatreLocation , string> Locations { get; } = new Dictionary<TheatreLocation , string>();
   
        public MovieSystem MovieSystem { get; };
              
        public MovieSystemPanelViewModel() 
        {
            // Fill up data in dictionary
            foreach (Enum item in Enum.GetValues(typeof(TheatreLocation)))
            {
                Locations.Add((TheatreLocation)item, ((TheatreLocation)item).GetDisplayName());
            }
        }
}

Write a Extension method in project somewhere, for display member according to requirement.

public static string GetDisplayName(this TheatreLocation location)
{
            switch (location)
            {
                case TheatreLocation.CityCentre:
                    return "Center city location";

                case TheatreLocation.CityNorth :
                    return "Northern city location";

                case TheatreLocation.CitySouth :
                    return "Southern city location";

                case TheatreLocation.CityEast :
                    return "Eastern city location";

                case CameraLocation.CityWest :
                    return "Western city location";

                 default:
                    return "Unknown";
            }
}

Now Bind xaml with these properties and methods.

<ComboBox 
         ItemsSource="{Binding Path= DataContext.Locations, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
          SelectedIndex="{Binding Path =Location , Mode=TwoWay, Converter={StaticResource MovieSystemLocationConverter}}">
            <ComboBox.ItemTemplate>
                  <DataTemplate>
                             <TextBlock Text="{Binding Path=Value}" />
                   </DataTemplate>
              </ComboBox.ItemTemplate>
</ComboBox>
  • Related