I have a collection view that contains different custom cells.
These cells contain different content that varies in size.
The cells are defined in the Storyboard, so no registering needed in code.
All i want to do now is change the size in the delegate method depending on the content:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
id cellAtIndexPath = [collectionView cellForItemAtIndexPath:indexPath];
NSLog(#"The cell: %#", cellAtIndexPath);
...
e.g. calling sizeToFit methods and cumulating the sizes of the cells' subviews
...
}
The Method is called as expected for every cell, but cellAtIndexPath always returns NULL, no matter what i tried.
So i am not able to access the cell object at the indexPath or its content view.
Any suggestions why i cannot access the cell object?
The collectionView:layout:sizeForItemAtIndexPath method is called by the collection view's flow layout object. The layout is asking for the size of a cell at a time before the cells are added to the collection view. You will have to compute the desired cell size "on your own" and return it.
Related
I applied gesture recognizer on particular UICollectionViewCell. It works fine. But after reloading the uicollectionview, this gesture recongizer is applied rest on collectionviewcell.
Suppose i have 10 cells. I apply gesture recongizer on 1st, 3rd, 4th,6th,7th,9th cells. Rest of cells 2nd,5th,8th cells don't have gesture recognizers. It works perfect on first time. After reload the collection view, 2nd,5th,8th cells also have gesture recognizer but i don't want. How to solve this issue. Please help me.
This is because UICollectionView reuses cells that are not visible any more. (Suppose you have 100 cells and only 8 visible - UICollectionView will keep at least 8 cells initialized, others might be reused) mwthod:
– dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:
Thus, in your method:
- (UICollectionViewCell *)cellForItemAtIndexPath:(NSIndexPath *)indexPath
When you dequeue your cell, you should resetup gesture recognizers or remove if you don't need them
You should always attach your gesture recognizers to the collection view itself—not to a specific cell or view. The UICollectionView class is a descendant of UIScrollView, so attaching your gesture recognizers to the collection view is less likely to interfere with the other gestures that must be tracked. In addition, because the collection view has access to your data source and your layout object, you still have access to all the information you need to manipulate cells and views appropriately.
https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/IncorporatingGestureSupport/IncorporatingGestureSupport.html
I am currently playing around with some demo projects for the new UICollectionView.
Most of this demos override layoutAttributesForItemAtIndexPath in there subclasses. But the method is never called in one of that example.
From the Apple docs i know that i have to override layoutAttributesForItemAtIndexPath
I cannot not figure out in which situation this method is called.
Is this method just for special cases?
Maybe you can find out in Apple doc, Subclasses must override both layoutAttributesForElementsInRect and layoutAttributesForItemAtIndexPath
read this:
layoutAttributesForElementsInRect:
Returns the layout attributes for all of the cells and views in the specified rectangle.
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
Parameters
rect
The rectangle (specified in the collection view’s coordinate system) containing the target views.
Return Value
An array of UICollectionViewLayoutAttributes objects representing the layout information for the cells and views. The default implementation returns nil.
Discussion
Subclasses must override this method and use it to return layout information for all items whose view intersects the specified rectangle. Your implementation should return attributes for all visual elements, including cells, supplementary views, and decoration views.
When creating the layout attributes, always create an attributes object that represents the correct element type (cell, supplementary, or decoration). The collection view differentiates between attributes for each type and uses that information to make decisions about which views to create and how to manage them.
Availability
Available in iOS 6.0 and later.
Declared In
UICollectionViewLayout.h
I have an observable collection with some objects in it. These objects have 4 strings a piece in them. I want to be able to display this data in a datagrid, but not like you'd think. If I let it auto generate columns, then I get a column for each field. What I need is a set amount of columns, for my items to be added as a custom template into each cell. It should start at the top left, and continue to the right, and restart at the end of every row.
For example: Let's say I have 10 items, and 3 columns. I should automatically have 3 rows with 3 columns a piece, and 1 item on the bottom row. These items will consist of 4 textblocks that display the data correctly.
I cannot figure out how to make a datagrid behave this way. I'm starting to think that another control may work better, but I'm unsure. If anyone can help with the datagrid, or point me in the right direction with another control, I'd really appreciate it.
Thanks in advance!
Sounds like you're looking for WrapPanel. Although you would have to supply the items you want in the list individually, not part of the object. You could bind to a IEnumerable that iterates over your object list and then returns each string piecemeal.
public IEnumerable<String> SomeList
{
get
{
foreach (var item in SomeOtherList)
{
yield return item.String1;
yield return item.String2;
yield return item.String3;
yield return item.String4;
}
}
}
I'm trying to create an extended version of the WinForms DataGridView (ElementDataGrid) to allow sorting and filtering. Since this will be a widget used by multiple developers, I want to hide the SortableBindingList class internally and have the user pass in just a normal List with the control creating the SortableBindingList.
I created a base class called Element, which other developers can extend, but when I set the DataPropertyName of a column to a property that isn't in Element, nothing shows up in that column. As an example, I have a Comment class that inherits from Element. I want to display the Comment Date and Comment Text in the datagrid. Neither of those columns have any data in them, but the columns using properties inherited from Element display properly.
Is there a straightforward way to have the grid display property values from classes that inherit from the Element base class? Alternately, is there a way I could have the property take a generic List?
UPDATE: Here's the method I'm using to set the data source to my SortableBindingList. As I said, properties from Element are being populated in the grid when I want to show them, but properties from Comment, which inherits from Element are not.
public List<Element> DataElements
{
set
{
bindingDataSource.Clear();
SortableBindingList<Element> boundDataSource = new SortableBindingList<Element>();
bindingDataSource.DataSource = boundDataSource;
foreach (Element e in value)
{
bindingDataSource.Add(e);
}
this.DataSource = bindingDataSource;
}
}
Take a look at Marc Gravell's answer to this SO question. Assuming, as he talks about in his answer, that the data is homogeneous (meaning that you aren't mixing Comments and SomeOtherClass in your List of Element) and has at least a single element in it (so that it is able to infer the actual type of the data in the list), I think it would work for your situation.
I have a radgridview which is bound to an object that I created, foo.
Object foo has a property 'status' that is populated from an enum.
I have many foo objects stored in a collection, which I use to bind to my radgridview.
Upon binding I get records and the grid displays fine.
I'd like to not display the 'status' enum value from my foo object within the grid. Instead, I'd like to use separate images that will depict the status more clearly (and in less space). Example, if foo's 'status' enum value == Open, I will display an open door and value == Closed would be a closed door. So the same column could have different images, but from the same property bound by foo's status enum. Hopefully that's clear enough...
I have tried overriding the content value with a bitmapimage within the RowLoaded event of the grid. I have also tried setting the data type of the grid to image, butmapimage, and image source to no avail...
Seems like this should be much easier than it is... If the image came straight from the database, it wouldn't be a problem; there's plenty of examples out there. However, doing it dynamically AND through code remain a mystery.
Thanks in advance for any assitance!
Apparently all I needed was to post the question...
I fell victim to trying way too many things at once and a soultion that should have worked perfectly didn't because I was trying a style on a cell at the same time.
In the example provided above, within the grid's RowLoaded event, one could do the following:
Get the enum value from the cell content
Create an Image control ( System.Windows.Controls.Image img = new Image(); )
Assign the image's source depending upon the enum value ( open.png / closed.png )
Set the cell's content = to the image control you just created
When the grid displays, you should see your image in the grid cell...
You also need to ensure the column's datatype is set to:
typeof( System.Windows.Controls.Image )