How to replace current control in Silverlight/WP7 with a transition? - silverlight

I have a Wp7 that has two controls. One is a map, and the other is a panorama control. In one of the panorama items is a list of values. If a user clicks on a list item, I'd like to show a turnstile transition to a new control that shows more detail.
So far in XAML, I have an event bound to LeftMouseUp, and it triggers. However I'm now sure how to replace the current panoramaitem with a new control (view), or how to use a the TurnstileTransition provided by the silverlight toolkit, between the two.
TurnstileTransition transitionElement =
new TurnstileTransition { Mode = TurnstileTransitionMode.ForwardIn };
AlertDetailedView view = new AlertDetailedView();
view.DataContext = (e.OriginalSource as FrameworkElement).DataContext;
//this stuff below sorta doesnt really work...
ITransition transition = transitionElement.GetTransition(this);
transition.Completed += delegate
{
transition.Stop();
};
transition.Begin();

In order to fit in with WP7 Navigation (e.g. the Back Button) then I'd recommend that you use two different pages for the two controls.
For seeing how to animate page transitions, then the SL toolkit contains some helpful material - or Kevin Marshall's blog is also very helpful - e.g.
http://blogs.claritycon.com/kevinmarshall/2010/05/12/windows-phone-7-prototype-002-animated-page-transitions-writeable-bitmaps/

Related

Re-navigate to a particular view in multi-view region

I'm working on a WPF application that's utilizing the Microsoft Prism framework. One aspect of the application is a "modal" region that can hold any number of modal windows that overlays over the entire window. As more views are navigated into the region, each window slides to the right to allow the new window to occupy the center of the screen. Here's a more visual explanation:
When the "modal" region contains a single view:
When another view is added to the region:
When several more views are added:
I have this working using a custom control that manages the animation and display of its children. Here's what the control's custom RegionAdapter's Adapt method looks like:
protected override void Adapt(IRegion region, ModalContainer regionTarget)
{
region.ActiveViews.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler((o, e) =>
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
foreach(FrameworkElement element in e.NewItems)
{
regionTarget.AddChild(element);
}
}
else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{
foreach (FrameworkElement element in e.OldItems)
{
regionTarget.RemoveChild(element);
}
}
});
}
My question is this: What's the best way to navigate back to an earlier window? Right now, the only way I know to trigger the RemoveChild method above is to explicitly remove the view from the region, which requires that I keep a list of all the views currently in the region somewhere:
// to remove the most recently added view from the region
_regionManager.Regions["ModalRegion"].Remove(addedViews.Pop());
Ideally, I would be able to navigate backwards using Prism's "journaling" concept, but I don't see a way in my RegionAdapter to respond to when a view already in the region is re-navigated to.
Any hints would be much appreciated.
EDIT
I was able to achieve this functionality by following a suggestion by GOstrowsky (see the comments in the accepted answer) - I changed my region adapter to only maintain a single active view in the region (the view currently in the center of the screen). I then can target that view for removal via myRegion.ActiveViews.FirstOrDefault().
YET ANOTHER EDIT
I have since changed this implementation yet again, as we needed the ability to remove any of the views currently in the region, not just the last one. See the accepted answer for details.
If you would ocassionally want to Navigate back to a previous View, you should not remove it from the Region when Navigating from it.
Instead, you could just deactivate it from the OnNavigatedFrom() method. And then, use the NavigationJournal to navigate back.
Regarding your RegionAdapter control you could modify it so that it could handle View activation and de-activation. For example, you could Publish a De/ActivationChanged event from each ViewModel OnNavigatedFrom() and OnNavigatedTo(), and handle these events on your custom control by Subscribing to it and performing the corresponding task to each event.
You can find more information about Navigation and Event Aggregation in the following MSDN Prism Guide chapters:
8: Navigation
Event Aggregation
I hope this helps,
Regards.
Initially, I solved this problem by only allowing a single region to be active, which guaranteed that removing the region's currently active view always removed the view currently in the center of the screen. However, since then, we've needed the ability to remove any of the views from the region, not just the first. To accomplish this, I realized that the Region.Views property can be cast to a List and then accessed by index:
List<object> allViews = modalRegion.Views.ToList<object>();
I'm a little uncomfortable with this solution, since the IViewsCollection definition inherits from IEnumerable, not IList; technically I could be handed a custom IViewsCollection that cannot be cast to an IList.... but in the short term I'm going to run with this.

wpf dual monitor application?

I'm very new to WPF. I want to create a dual monitor/projector application. What I want to do is have the "presenters screen" on one monitor and another panel on the secondary monitor, similar to how powerpoint works. I'm struggling to wrap my mind around the panels and XAML. So what I'm after is user clicks on a button on screen1 and information gets updated on screen2.
I'm using this code:
this.Width = System.Windows.SystemParameters.VirtualScreenWidth;
this.Height = System.Windows.SystemParameters.VirtualScreenHeight;
this.Top = 0;
this.Left = 0;
to set the width and height of the screen.
Edit:
The later goal is to cause screen2 to retrieve items out of a database based on the selection on screen1
Question: tutorials, places to go, nudges on how to update monitor2 from a button on monitor1
Short Answer
Create a view model that shared between two views; make one of the views the master (makes the changes) and the other pure presentation. The views are new windows. Initially do not be concerned with the window position (we'll get to that later) just get the shared viewmodel working.
Tip: research the MVVM pattern. Google has a lot of articles on the subject.
Long Answer
After you have researched MVVM and created a few example applications (from scatch or using a framework), below are few additional features you want implement to create the "powerpoint-like" application.
Fullscreen Mode
At the very least you will want the presentation window to be full screen. To achieve this, you set the WindowStyle to None and AllowsTransparency to True.
If you want to make the second window also fullscreen you may need to do some Win32 overrides to get the window to maximize properly without covering the taskbar (post a comment if you want to know how to do this).
Detect Multiple Monitors
Get the size and position of the monitors using Win32 Interop commands. There will be plenty of articles on the Internet that will help you with this (or post another StackoverFlow question).
This would be a neatâ„¢ feature as it will position the two windows correctly (use the secondary screen as the presentation).
That is all that I can think of now, post-back if you any questions on MVVM or any of the additional points above.
1) You should have 2 Windows, the way this looks I'd make monitor2 a child window of monitor1 (after all, it is a child ;)
What i mean by that, is that StartupUri in App.xaml should point to monitor1, and in monitor1's constructor, you should create an instance of monitor2 (which would be a singleton if i were to do it).
2) To maximize a window on the second screen:
Subscribe to the Loaded event of the window (in code-behind), and set
private void Window_Loaded(object sender, RoutedEventArgs e) {
WindowState = WindowState.Maximized;
}
More info (and source): here
3) As to how to make monitor2 react when you set something in monitor1, make monitor1 and monitor2 bind to the same ViewModel, only they show different stuff.
Hope this helps!

MVVM - How do I open a window based on a selected item from a list?

I am quite new to the WPF & MVVM world, and have spent the last few days downloading as many tutorials as I could, and reading as much as possible!
I am however struggling to implement with a very basic and common concept with MVVM and am desperate for some help - and perhaps even an example :-)
I've got the basics of M-V-VM, commanding, and even messenging; but how on earch do I open a new window and set that windows ViewModel to the selected item of a listbox?
Let me explain:
I have a Model called Client and it has some properties
I then have a ViewModel which gets all my Clients and stores them in an ObservableCollection
I have a screen where I display the Name & Surname in a listbox and allow the user to filter and search.
All of the above work perfectly.
When a user selects an item though, I would like to open an editable "detailed client view" screen of that particular client. This detailed screen's ViewModel would need to somehow bind to the selected item (if that makes sense); or I need to be able to pass a paramter to the newly opened screen's ViewModel. In fact, if the user could open several detail screens at the same time and edit multiple clints it would be great!
If anyone can give me a nice example, or point me in the right direction I would truly be greatful!
Many thanks,
Brendan
I would add an event to the ListBox.SelectionChanged which does the following:
Creates a new Dialog and DialogViewModel
Binds the DialogViewModel.EditableContentProperty to the ListBox's SelectedItem
Dialog.DataContext = DialogViewModel
Dialog.ShowDialog()
Simply put:
//Create the Client Detail form
frmClientDetails frm = new frmClientDetails();
frm.Owner = this;
var ViewModel = new ClientDetailViewModel((Client)lstFoundClients.Items.CurrentItem);
frm.DataContext = ViewModel;
frm.Show();

How to fix selected Item in a collection control on a user control (using the MVVM implementation) in WPF

I hope someone can help me...
Josh Smith did a great article on "WPF apps with the Model-View View-Model", and included in his article was the following code sample.
If you download the code sample and run the app and view all customers, then select a company (e.g. 4th company), then click "Create new customer" (which will open a tab of the new customer), and then click back on the "All Customers" tab, and then using the keyboard try and move the selected item up one to the item directly over the current selected item, it doesn't! Instead the selector starts at the top again.
I am not sure why this happens, but I want it so that when you click up, it goes one item up, rather than starting at the top of the list. I suspect this has to do with FocusManager, but am not sure.
Does anyone know why the control behaves in this manner? Is it possible, and what approach I should take to modify this code and get it to not "reset" the selected item?
I have implemented a project based off this template and for functionality reasons I need to get the keyboard to move the selector up & down without it resetting.
in the example you've provided setting IsSelected property does not affect the logical focus so the focus is set by default. Workaround I have in mind currently is to force focus for the element in codebehind. As an example add handler to selectionchanged of the listview like this:
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count == 0 || e.RemovedItems.Count > 0) return;
var item = (CustomerViewModel) e.AddedItems[0];
var container = (UIElement) listView1.ItemContainerGenerator.ContainerFromItem(item);
container.Focus();
}

How to enable user to drag/drop WPF user controls anywhere on the page?

Now that I can make useful user controls in WPF (thanks to this stackoverflow answer) I want to be able to put numerous user controls on one page in two columns and enable the user to be able to move them around according to preference, dragging the ones they use the most to the top, etc.
Can anyone point me to code, tutorials, etc. which do this? I can imagine this has been made quite easy to do in WPF.
Here is a blog post to get you started on drag drop functionality in WPF.
Have Fun.
There's also How can I drag and drop items between data bound ItemsControls? by Bea Stollnitz.
The article talks about a reusable set of adorners that enable drag-n-drop between controls.
It's somewhat advanced, but very useful.
A series of blog posts that deal with Drag and Drop using attached properties.
I know this isn't exactly what you need but it might get you close!!!
Martin Grayson has a project on Codeplex called Blacklight... Check out the Drag dock Panel!!!
I was looking for an easy way to accomplish this as well and came across the following web page: http://dotnetslackers.com/ADO_NET/re-191632_Generic_WPF_Drag_and_Drop_Adorner.aspx It looks like there are some nice features of this implementation.
For future reference, there is a great library on codeproject that has a DragCanvas which enables you to drag any controls placed on it:
http://www.codeproject.com/KB/WPF/WPFJoshSmith.aspx
It also contains a CenteredContentControl if you want to make "attachments" between controls.
Correction:
private void Control_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
isDragging = true;
var draggableControl = sender as UserControl;
clickPosition = e.GetPosition(this.Parent as UIElement);
var transform = RenderTransform as TranslateTransform;
if (transform != null) {
clickPosition.X -= transform.X;
clickPosition.Y -= transform.Y;
}
draggableControl.CaptureMouse();
}

Resources