Hi,
I am trying to write a Prism (CAL) adapter for the XamTilesControl, and in my implementation I would like to have only one active tile, and this tile should be the one and only maximized tile. So, maximizing a tile should make it's view active (easily handled by hooking into the TileStateChanged event), and when the view is made active programmatically then the tile should be maximized, and that's where I run into problems.
When a new view is added to the prism region, I add it to the tile control, then I attempt to get the tile by calling TileFromItem(), but this returns null. :( After reading some other posts I tried calling UpdateLayout() first, but that didn't help, but after a little more reading I found another suggestion to use Dispatcher.BeginInvoke(). In the end I had to use the following code (_instance is my XamTilesControl):
_instance.Dispatcher.BeginInvoke((Action)(() => { _instance.UpdateLayout(); Tile tile = _instance.TileFromItem(e.NewItems[0]); if (tile != null) { tile.State = TileState.Maximized; } }));
This did allow me to access the Tile for the view, and to set it's state to Maximized, but unfortunately it doesn't actually maximize the view! Instead the view appears to be still in normal mode, but it does have a minimize button (as opposed to a maximize button when I don't set the tile state to Maximized), which implies that the tile thinks it's maximized! If I click the button it changes to a Maximize button and the tile remains the same, when I click it again it maximizes.
So I have two problems, first I would like to know the proper way to obtain the Tile after adding an item to the Items collection, and second I would like know how to maximize the tile programmatically. If anyone has any ideas I would be very grateful.
Thanks.
Brian
Hi Brian,
I am aware of an issue that was resolved in earlier service releases concerning a newly added tile not being visible without using threading. It was an older issue prior to the release of 2011.1. Please let me know what product and service release you are using.
Secondly you mentioned that you want to only have one maximized tile at a time. The xamTilesControl MaximizedModeSettings has a property, MinimizedTilesExpansionMode, which you can set to AllowOne to allow only one maximized tile at a time.
It appears that you are using the appropriate method to acquire the tile that you want to maximize by using Tile tile = tilesControl.TileFromItem(item). And setting the tile’s State to TileState.Maximized should cause that tile to be maximized and, in conjunction with the previous setting I mentioned, cause it to be the only maximized tile.
I’m a little confused if your code is in the TileStateChanged event or some other event. The TileStateChanged event should provide you with the affected tile directly from the arguments.
It might be helpful if you could provide me with a small sample.
Hi Marianne,
I am using the latest version of the Infragistics libraries, with the latest service release: 11.1.20111.2113.
I am writing an adapter for the XamTilesControl to be used with the Prism framework, and the code to add the tile is being executed inside an event handler that is called when a new view is added to the Prism region. If you're not familiar with Prism, I think this event is probably being raised from within the "OnChanged" handler for an attached property, which is being set in the XAML for the view that I am trying to add to the tiles control. Hope that makes sense. :/
If you create a simple WPF application and add a tile control to the main window, then add the code below in the code behind file, it will partially replicate the problem:
private void Window_Loaded(object sender, RoutedEventArgs e) { String testItem = "Item1"; xamTilesControl1.Items.Add(testItem); Tile tile = xamTilesControl1.TileFromItem(testItem); if (tile != null) { // This is never reached! tile.State = TileState.Maximized; } else { // delay the maximizing of the tile until after tile is created xamTilesControl1.Dispatcher.BeginInvoke((Action)(() => { xamTilesControl1.UpdateLayout(); Tile lazyTile = xamTilesControl1.TileFromItem(testItem); // if we have a tile now if (lazyTile != null ) { lazyTile.State = TileState.Maximized; } }) //, DispatcherPriority.ContextIdle ); } }
The tile is always null when first added here, so the dispatcher is used to delay setting the state to Maximized. This works for this simple scenario, but in my actual scenario it doesn't (I can get the tile, but setting the Maximized state does not actually cause the window to get maximized), however adding the DispatcherPriority.ContextIdle parameter (commented out in the code above) seems to fix my problem! :)
It looks like some kind of timing issue to me, so my concern is that my workaround may not be reliable, and it would be much better if I could obtain the tile as soon as I add the new view, and then set it's state to Maximized immediatly and have this actually maximize the tile when it's displayed. :)
Thank you for the update. Please let me know if I can be of further assistance.
I just noticed that the headers of my tiles are no longer displaying the header text. Previously I had set the HeaderPath property of teh XamTilesControl to specify which property on my user control to bind to for this text, but this does not appear to work when you add Tile items directly. :(
I have had to modify my adapter class to set each Tile's Header explicitly, and to do that meant I had to use a cast to convert it's contained user control's DataContext to my view model type, which makes it more tightly coupled than I would like. :(
Is there a way to have the Tile bind it's Header to a property of it's Content object, possibly by specifying a HeaderPath as the XamTilesControl does?
Thanks,
The HeaderPathProperty is the xamTilesControls’ dependency property for setting the path to a value in the source that will be used to initialize the Header of each Tile and you can bind to it. I’m guessing that you set the HeaderPath in code.
The tiles also have a HeaderProperty which is a dependency property. You can also set each tile's header as I did in my snippet when I add a single tile.
I think the question is how are you setting / binding to this property? Or are you binding to this property? You should be able to set the HeaderPath or Header of each tile.
Thanks for the info, I hadn't realized that I could just bind to the Header property! :) I have solved my problem with the code below:
// NB: This would be a reference to the actual user controlUserControl myControl = new UserControl();
// configure binding for headerBinding bind = new Binding("DisplayName");bind.Source = myControl.DataContext;bind.Mode = BindingMode.OneWay;
// add control to a new tileTile tile = new Tile() { Content = myControl };
// set binding for Headertile.SetBinding(Tile.HeaderProperty, bind);
// add tile to tiles controltilesControl.Items.Add(tile);
Thanks for your help.
Glad I could help and thanks for posting your solution code here for the next person.
Please let me know if you have any further questions.