1

My project was working good before I made some changes in my database and my code.

Before Changes :

Output :

Tile1    Tile7    ..........    Tile(N-x)
Tile2    Tile8                  Tile(N-x+1)
Tile3    Tile9                  ....
Tile4    Tile10                 ....
Tile5    Tile11                 ....
Tile6    Tile12                 Tile(N)

Table in Database: 1------- [Primary Key] Title | Background | Image | ParentID *------- [Foreign Key]

XAML :

<ListBox Grid.Row="1" x:Name="lst"
         ItemsSource="{Binding ChildrenMenus}" >

    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel IsItemsHost="True" Orientation="Vertical" MaxHeight="{Binding ElementName=lst, Path=ActualHeight}"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>

    <ListBox.Resources>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="Width" Value="250" />
            <Setter Property="Height" Value="125" />
            <Setter Property="Margin" Value="2.5" />
            <Setter Property="Padding" Value="2.5" />
            <Setter Property="Background" Value="{Binding Background, Converter={StaticResource stringToBrushConverter}}" />
            <Setter Property="Foreground" Value="White" />
            <Setter Property="VerticalContentAlignment" Value="Bottom" />
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Foreground" Value="{Binding Background, Converter ={StaticResource stringToBrushConverter}}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </ListBox.Resources>

    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" Height="125" Width="250">
                <Path Data="{Binding Image}"  VerticalAlignment="Center" 
                      Stretch="Uniform" Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"
                      Width="68" Height="68" Margin="10" RenderTransformOrigin="0.5,0.5">
                    <Path.RenderTransform>
                        <TransformGroup>
                            <TransformGroup.Children>
                                <RotateTransform Angle="0" />
                                <ScaleTransform ScaleX="1" ScaleY="1" />
                            </TransformGroup.Children>
                        </TransformGroup>
                    </Path.RenderTransform>
                </Path>
                <TextBlock Text="{Binding Title, Converter={StaticResource spaceToNewLineConverter}}" VerticalAlignment="Top" 
                           Margin="40,10,10,10" FontSize="24" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>

</ListBox>

Currently:

Required Output:

Text1     Text2            Text3             ..........     Text(N)

Tile1     Tile3  Tile7     Tile9    Tile13                  Tile(N-x)        .....
Tile2     Tile4  Tile8     Tile10                           Tile(N-x + 1)    .....
          Tile5            Tile11                           ....             .....
          Tile6            Tile12                           ....             Tile(N)

Changes in database:

enter image description here

I have tried many changes in ViewModel and XAML files and now it got messed up. So, if I post those codes then also it will not be useful to anybody.

I hope I have mentioned everything correctly in question.

Update

First of all I am sorry. My internet connection was down for the whole day. I have read your messages just now.

Now, I have got something. I can get data from database in Design_Master_MenuItems. See the Image below:

enter image description here

But still Binding does not work correctly. I mean my ListBoxes inside ItemsControl are not being populated.

Here is my current XAML:

<ItemsControl ItemsSource="{Binding MenuCategories}" >

    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel IsItemsHost="True" Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid >
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>

                <TextBlock Text="{Binding Title}" FontSize="30" />

                <ListBox Grid.Row="1" x:Name="lst"
                         ItemsSource="{Binding Design_Master_TileItems}" DisplayMemberPath="Title">

                </ListBox>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Here is myViewModel :

public class MainWindowViewModel : ViewModelBase
{

    public MainWindowViewModel()
    {
        using (Entities db = new Entities())
        {
            ParentMenus = new ObservableCollection<Design_Master_ParentMenus>(from d in db.Design_Master_ParentMenus select d);

            if (SelectedParent != null)
                MenuCategories = new ObservableCollection<Design_Master_Categories>(from d in db.Design_Master_Categories
                                                                                  where d.ParentMenuID == SelectedParent.ParentMenuID 
                                                                                  select d);
        }
    }

    private ObservableCollection<Design_Master_ParentMenus> _parentMenus;
    public ObservableCollection<Design_Master_ParentMenus> ParentMenus
    {
        get
        {
            return _parentMenus;
        }
        set
        {
            _parentMenus = value;
            OnPropertyChanged("ParentMenus");
        }
    }

    private Design_Master_ParentMenus _selectedParent;
    public Design_Master_ParentMenus SelectedParent
    {
        get
        {
            return _selectedParent;
        }
        set
        {
            _selectedParent = value;
            OnPropertyChanged("SelectedParent");

            using (Entities db = new Entities())
            {
                MenuCategories = new ObservableCollection<Design_Master_Categories>(from d in db.Design_Master_Categories
                                                                                  where d.ParentMenuID == SelectedParent.ParentMenuID
                                                                                  select d);
            }
        }
    }

    private ObservableCollection<Design_Master_Categories> _menuCategories;
    public ObservableCollection<Design_Master_Categories> MenuCategories
    {
        get
        {
            return _menuCategories;
        }
        set
        {
            _menuCategories = value;
            OnPropertyChanged("MenuCategories");
        }
    }

}

Yes, and I will not be available for next 10 hours. If you find any mistake in the above code you may comment. Thanks for a big helping hand.

Update2

Yes now I find the binding error in Output window:

System.Windows.Data Error: 17 : Cannot get 'Design_Master_TileItem' value (type 'ICollection`1') from '' 
(type 'Design_Master_Catego_79D2EFE4D31EC6575261E40C340C9D078D37C022F94C70A5F8A88A9017957C24').     
BindingExpression:Path=Design_Master_TileItem; 
DataItem='Design_Master_Catego_79D2EFE4D31EC6575261E40C340C9D078D37C022F94C70A5F8A88A9017957C24' 
(HashCode=28842409); target element is 'ListBox' (Name=''); target property is 'ItemsSource' (type 
'IEnumerable') TargetInvocationException:'System.Reflection.TargetInvocationException: Property accessor 
'Design_Master_TileItem' on object
'System.Data.Entity.DynamicProxies.Design_Master_Catego_79D2EFE4D31EC6575261E40C340C9D078D37C022F94C70A5F8A8
8A9017957C24' threw the following exception:'The ObjectContext instance has been disposed and can no     
longer be used for operations that require a connection.' ---> System.ObjectDisposedException: The 
ObjectContext instance has been disposed and can no longer be used for operations that require a 
connection.

System.Windows.Data Error: 17 : Cannot get 'Design_Master_TileItem' value (type 'ICollection`1') from '' 
(type 'Design_Master_Catego_79D2EFE4D31EC6575261E40C340C9D078D37C022F94C70A5F8A88A9017957C24'). 
BindingExpression:Path=Design_Master_TileItem; 
DataItem='Design_Master_Catego_79D2EFE4D31EC6575261E40C340C9D078D37C022F94C70A5F8A88A9017957C24' 
(HashCode=13006057); target element is 'ListBox' (Name=''); target property is 'ItemsSource' (type 
'IEnumerable') TargetInvocationException:'System.Reflection.TargetInvocationException: Property accessor 
'Design_Master_TileItem' on object 
'System.Data.Entity.DynamicProxies.Design_Master_Catego_79D2EFE4D31EC6575261E40C340C9D078D37C022F94C70A5F8A8    
8A9017957C24' threw the following exception:'The ObjectContext instance has been disposed and can no 
longer be used for operations that require a connection.' ---> System.ObjectDisposedException: The     
ObjectContext instance has been disposed and can no longer be used for operations that require a       
connection.
Vishal
  • 6,238
  • 10
  • 82
  • 158
  • Are you asking which WPF control to use for display? – BradleyDotNET Mar 03 '14 at 18:00
  • 1
    +1 for including a lot of details, just missing exactly what you are looking for help with. – BradleyDotNET Mar 03 '14 at 19:53
  • @LordTakkera Yes, you are absolutely right. I am asking which Container should fit best in this case and also if you can then please provide an example. – Vishal Mar 03 '14 at 23:27
  • I don't see anything obviously wrong. Are any data binding exceptions appearing in your output window? Are the "big" blocks appearing correctly except for the list box? Does it work with a data grid or list view? – BradleyDotNET Mar 04 '14 at 18:33
  • you can download sample project here : https://drive.google.com/file/d/0B5WyqSALui0bM05BSVRia2VCcFk/edit?usp=sharing – Vishal Mar 05 '14 at 13:45
  • @LordTakkera I have updated my question. Please see Update2 for binding errors that I get. – Vishal Mar 05 '14 at 16:30
  • I used .ToList() and removed using instead I declared Entities db = new Entities. And now I get items in my listBoxes. – Vishal Mar 05 '14 at 16:51
  • Now, I have created a property like : Public Design_Master_TileItem SelectedTile { get; set; } and binded it to the selectedItem of ListBox using RelativeSource. But still I am able to select items from both listboxes. – Vishal Mar 05 '14 at 16:57
  • I added some stub code that should get you close to having only one list box selected at a time. Let me know how it works! – BradleyDotNET Mar 05 '14 at 17:28
  • I have tried to use the converter you just mentioned in your answer. But I am getting an error that : `A 'Binding' cannot be set on the 'ConverterParameter' property of type 'Binding'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject."` So, I tried to create a dependency property in MainWindowViewModel class. But then it gives me another error saying that my MainWindowViewModel should inherit from DependencyObject. But my MainWindowViewModel already inherits from BaseViewModel and upto my knowledge one class in C# cannot inherit from multiple classes. – Vishal Mar 05 '14 at 18:37
  • Sorry, forgot about that. You need to set it up as a MultiValueConverter so you can pass yourself in as part of the value object (no parameter). An example of how to do this can be found here: http://drwpf.com/blog/2007/08/18/can-my-value-converter-access-the-target-of-the-binding/ I will try to update my answer with similar code as well. – BradleyDotNET Mar 05 '14 at 19:48
  • What do you mean by "." in the Converter Parameter Binding? Does it mean that you are binding to SelectedTile Property? – Vishal Mar 05 '14 at 19:48
  • It means "Bind to my data context" or "Bind to myself", I just realized I need to make sure this is going to work, since SelectedItem is on the ListBox (not the item) – BradleyDotNET Mar 05 '14 at 19:53
  • My way was going to get complicated really fast, and I updated my answer to include a link to an answer that (should) solve this problem. – BradleyDotNET Mar 05 '14 at 19:59
  • If you get a chance, and find my answer useful, I'd appreciate an upvote/accept as well. – BradleyDotNET Mar 05 '14 at 20:00
  • I should have been clearer earlier, "." means bind to the current data context. It does NOT bind to the control, which could have been implied by my saying "Bind to myself". – BradleyDotNET Mar 05 '14 at 20:02
  • OK, I will be trying that answer and let you know the results. Thank you very much for a great helping hand and thanks again for taking time and keeping patience. – Vishal Mar 05 '14 at 20:07
  • Not a problem, "Best way to select one of many listbox options" could be a good question in its own right, if you are interested in other people's opinions. – BradleyDotNET Mar 05 '14 at 20:09
  • Yes, that helps me upto some extent. I mean When I click an Item in first listbox the item is selected. After that when I click on an item in second listbox the selection from first listbox is cleared out but no item is selected in second listbox. Then when I click on an Item in second listbox the item is selected. – Vishal Mar 05 '14 at 20:19
  • Also I get warnings : GroupName property was already registered by Selector. – Vishal Mar 05 '14 at 20:35
  • Does it work? If it does, you can probably ignore the warnings. At this point, the behavior you want would be better served by a new question, I don't have any answers off the top of my head. I will gladly still help if you have trouble with the XAML collection/layout piece, and if I think of something I would be happy to answer the new question. – BradleyDotNET Mar 05 '14 at 20:39
  • So, I changed GroupName to SelectedGroup in the Class as well as reference in xaml and I don't get the warning anymore. Also I think that the issue of selection I am facing is because when I click on an Item in Second ListBox the first click will be for ItemsControl and on second click the Item is selected. So, I need to put ItemsControl's click to silent mode. – Vishal Mar 05 '14 at 20:41
  • Glad you were able to figure it out! – BradleyDotNET Mar 05 '14 at 20:44
  • I got it. I have added a trigger in ListBoxItem's Style : – Vishal Mar 05 '14 at 20:45
  • Makes sense, does your application behave as expected now? – BradleyDotNET Mar 05 '14 at 20:46
  • Yes, it behaves as expected. Thank you for helping me. Also for the keyboard issue we discussed day before yesterday I will ask a new question now. Thanks again. – Vishal Mar 05 '14 at 20:48
  • I have asked another question. Here is the link : http://stackoverflow.com/questions/22209877/movefocus-from-one-listbox-to-another#22209877 If you get any answers then please post. – Vishal Mar 05 '14 at 21:56

1 Answers1

1

First you want a ListView with a horizontal StackPanel as the panel template to get your "big" blocks.

Then, for each block, you'll need a "header" and then another ListView, this time with a vertical WrapPanel as the panel template. Below is a "shell" example that would need some styling and bindings to get it to look exactly the way you want, but hopefully it gets you on the right track.

<ListView>
   <ListView.ItemsPanel>
       <ItemsPanelTemplate>
           <StackPanel Orientation="Horizontal"></StackPanel>
       </ItemsPanelTemplate>
   </ListView.ItemsPanel>
   <ListView.ItemTemplate>
       <DataTemplate>
           <StackPanel>
               <TextBlock/>
               <ListView>
                   <ListView.ItemPanelTemplate>
                       <WrapPanel Orientation="Vertical"></WrapPanel>
                   </ListView.ItemPanelTemplate>
                   <ListView.ItemTemplate>
                       <DataTemplate>
                           <TextBlock/>
                       </DataTemplate>
                   </ListView.ItemTemplate>
               <ListView>
           </StackPanel>
       </DataTemplate>
   </ListView.ItemTemplate>
<ListView>

Update:

To have only "one selection", make sure that selecting either list box calls the setter on your property. I normally don't do this with RelativeSource, so here is an example if you want to try it (where your window/user control is named "Root":

"{Binding ElemantName=Root, Path=DataContext.SelectedTileItem}" 

A converter is going to get really complicated to do this. This answer has an accepted way of setting up what you are trying to do, and it is probably the way you want to go (I would use the group name route, since that is basically what you are trying to do).

Community
  • 1
  • 1
BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
  • That's a great answer. Now I have two problems with your answer. (1) First Listview for making big blocks will allow me to select a block. But I don't need a selection. And also (2) why should I use ListView instead of ListBox for creating tiles? I should say thank you for this answer. Thanks. – Vishal Mar 03 '14 at 23:57
  • I believe ListBox would work just as well, I'm just used to using ListView. There are a couple of ways to make ListViews unselectable if you do want to go down that route. If you use ListBox, I would be interested in hearing if it is basically the same, or if there is some gotcha I forgot. – BradleyDotNET Mar 04 '14 at 00:09
  • Also another problem is that I should be able to select only one item from any inner ListView. I mean If I have two ListViews. Inside each ListView I have 1 ListView. So I should be able to select only 1 Item from either first listview or from second listview. And also when I work with arrow keys of keyboard I should be comfortable. I mean if I press right arrow on the first inner ListView, then if there is any Item in the first inner listview on the right side of the Currently Selected Item then that should be selected else focus should go to respective Item of second inner ListView's Item. – Vishal Mar 04 '14 at 00:13
  • I have used ItemsControl instead of ListBox. So problems in my first comment are solved. – Vishal Mar 04 '14 at 00:16
  • To accomplish the "only one selected" requirement, I would bind all the listbox's selected item properties to the same VM property and use a variant of the "ValueEqualsConverter": http://stackoverflow.com/a/2908885/1783619 – BradleyDotNET Mar 04 '14 at 00:18
  • As far as the keyboard goes, I would have to do a lot more research. That might be better as a seperate question. – BradleyDotNET Mar 04 '14 at 00:18
  • If you wish then I will ask a second question. – Vishal Mar 04 '14 at 00:20
  • I would do a separate question on the keyboard, are you good on the rest? – BradleyDotNET Mar 04 '14 at 01:13
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/48909/discussion-between-vishal-and-lordtakkera) – Vishal Mar 04 '14 at 01:15
  • I added a comment to the chat, but in case you don't see it, you can bind directly to the navigation property in EF. Let me know if that doesn't get you the behavior you want. – BradleyDotNET Mar 04 '14 at 03:19
  • Here is the declaration of that property public virtual ICollection Design_Master_TileItems { get; set; } I can't put a breakpoint on that but in constructor of that class it's new instance is created where I kept a breakpoint and I show that count always remains zero. But table in my database contains some data. I don't know what the problem is and also note that this class is auto-generated by ef. – Vishal Mar 04 '14 at 04:14
  • Try calling Load on the collection (potentially the entire collection instead of per instance) and binding to the .Local property instead. Nothing will work right until your EF classes are populating correctly, so you need to get this working first. – BradleyDotNET Mar 04 '14 at 05:15
  • Also, try binding the outer list directly to the context (instead of going through your intermediate collection). EF is lazy loaded, and what your doing might not cause the navigation property queries to fire, since EF doesn't know you are binding against them. – BradleyDotNET Mar 04 '14 at 05:25
  • I'm sorry I don't have more definitive answers for you, hopefully something I suggest will be of assistance. – BradleyDotNET Mar 04 '14 at 05:25
  • Were you able to get it working? I am available if you still need help. – BradleyDotNET Mar 04 '14 at 17:08
  • Please see Update part in my question. – Vishal Mar 04 '14 at 18:18