I'm developing a .NET 4.0 application using PRISM and MVVM, as well as WPF.
I currently have a shell subdivided in regions, with views inserted in them. When the user clicks on a button in one of the views, I would like a custom-made modal dialog to be displayed on top of all the views, but still within the same shell.
I looked at the StockTrader RI example and their implementation of the RegionPopupBehavior. Basically, they created a dependency property which allows them to define regions with a specific, custom-made behavior. The behavior is the one in charge of handling it's associated view's rendering, hence displaying it as a popup window.
The only downside to this approach is that all the other views are still active, so the popup isn't modal. I guess this can be resolved by manually disabling all un-needed regions in the shell, but I'm not sure how "clean" this is.
I was wondering if there were a better and simpler approach to displaying modal pop-up views in Prism ?
You might be interested in a custom PopupUserControl I have posted on my blog that behaves like that.
Usually I use it like this:
<local:PopupPanel
Content="{Binding PopupContent}"
local:PopupPanel.PopupParent="{Binding ElementName=SomeParentPanel}"
local:PopupPanel.IsPopupVisible="{Binding IsPopupVisible}">
<local:PopupPanel.Resources>
<DataTemplate DataType="{x:Type local:SomeViewModel}">
<local:SomeView />
</DataTemplate>
<DataTemplate DataType="{x:Type local:DifferentViewModel}">
<local:DifferentView />
</DataTemplate>
</local:PopupPanel.Resources>
</local:PopupPanel>
Although you can also just write the Content in the popup instead of binding the Content property
<local:PopupPanel
local:PopupPanel.PopupParent="{Binding ElementName=SomeParentPanel}"
local:PopupPanel.IsPopupVisible="{Binding IsPopupVisible}">
<Border BorderBrush="Blue" BorderThickness="2">
<local:MyUserControl />
</Border>
</local:PopupPanel>
Related
I have a window which has several different DataTemplate that are load to a ContentControl based on a RadioButton (The RadioButton sends a command to the ModelView which sets the Content property of the ContentControl.
It works well, but now several views contain a "heavy" object (Eyeshot CAD viewer).
Switching to any of these view causes a delay (at this moment there's absolutely zero logic in the whole software other than the view/view model)
Is there a way to load the view and the heavy control to memory once and then reuse it when switching to its view? (The ViewModel of that view is currently a singleton but that doesn't help)
<DockPanel>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Height="160" Margin="0,0,0,12">
... Removed for clarity
</StackPanel>
<ContentControl x:Name="Tabs" Content="{Binding SelectedTabViewModel}" Margin="0,12,0,12"/>
</DockPanel>
On your DataTemplate, you can set the attribute x:Shared="True", this will allow the framework to reuse the visual control (inside the datatemplate) for another ContentPresenter.
This doesn't load the component at starting, but, this reuse it once instantiated.
Hi I'm a newbie to windows store apps and i want to create a pop up that'll show image .I'm currently using Prism framework and tried many things.However , I'm successfully able to launch the pop up using code behind file but i need it from View Model class. Please help.
You can use default winrt popups but if you want popups developed by yourself this is the way.
Create modal dialog user control, structure is following
<Grid>
<Grid Background="Black" Opacity="0.4"/>
<Grid HorizontalAlignment="Center" VerticelAlignment="Center">
<!-- your popup xaml -->
</Grid>
</Grid>
Of course, you have to set ViewModel in some way, e.g. through ViewModelLocator
DataContext="{Binding Source={StaticResource ViewModelLocator}, Path=ModalDialog}">
Add this user control to your main view ( root view ) or to all views where you want to have popup.
<controls:ModalDialog Visibility="{Binding IsVisible, Converter={StaticResource BoolToVisibilityConverter}}"/>
After this you can implement some service or use messenger to show dialogs. I know that it is maybe not so understandable but it is difficult to describe in all details. Feel free to ask.
Could anyone explain how to use the XAML popups with Caliburn Micro.
Thanks
Edit:(Made my code more releavent to what I want to achieve)
When I define a popup in xaml like this:
<Button x:Name="ShowPopup" Content="Popup"/>
<Popup x:Name="my_popup_xaml" Grid.Row="2">
<Border BorderThickness="2" Margin="10" BorderBrush="Green">
<StackPanel Background="LightBlue">
<TextBlock Text="Select Option" FontSize="21" Margin="10,0" />
<StackPanel Orientation="Horizontal" Margin="0,10">
<Button x:Name="SelectPhoto" Content="Select photo From Library" Width="215"/>
<Button x:Name="CapturePhoto" Content="Use Camera" Width="215"/>
</StackPanel>
</StackPanel>
</Border>
</Popup>
How do I display this popup using the WindowManager?
Should I create new View Model for this because I just need to use PhotoChooser task and the Camera Capture task here?
How do I bind Popup to my View Model.
Edit:
#Charleh, Your Suggestion for using with windowmanager with a separate ViewModel worked, with a minor tweak.
I removed the <Popup> tag and used the window manager to display the popup.
But now I cannot close the popup and the popup is cropped as it's displayed at the top of the screen. How do I fix this?
Edit: I was able to close the dialog using the the Screen's TryClose() Method.
When I used the ShowDialog method instead the of the ShowPopupmethod and the alignment of the window was a bit better but it is still stuck at the top and wont align in the center.
Edit: I have created a new PhoneApplicationPage(Windows Phone 8 equivalent of window) and displayed it as a dialog. The problem with this approach is that the PhoneApplicationPage is not stretching automatically to fill the screen space(Which it does when not displayed as a dialog). It's just stretching to accommodate the content inside it. Setting `VerticalAlignment="Stretch" has no effect.
Giving the Height property a particular value is not suitable because of it does not adjust to well to different phone resolutions.
#Charleh I tried specifying height and width like this:
Dictionary<string, object> properies = new Dictionary<string, object>();
properies.Add("Height", 768);
properies.Add("Width", 480);
windowManager.ShowDialog(new ImageSelectorPopupViewModel(),null,properies);
This Code has no effect (although specifying the height in Xaml works but I cannot use that as I have to accommodate for different screen resolutions on the phone)
You really need to read up on Caliburn Micro before you post - there are literally tons of articles showing how to bind commands on your view to methods on your VM
To do so in this case either:
Bind using convention by giving your button the same name as the method
<Button x:Name="ShowPopup" />
Bind using action message syntax:
<Button cal:Message.Attach="[ShowPopup]" />
All the answers are here: http://caliburnmicro.codeplex.com/documentation
(specifically: http://caliburnmicro.codeplex.com/wikipage?title=All%20About%20Actions&referringTitle=Documentation)
You do the same thing with your button, so you can do the same thing with your popup
(have you also considered using Caliburns WindowManager which has a ShowPopup method?)
Edit:
On re-reading it looks like you want to use the same ViewModel for your current View and Popup - is this the case or do you want a new ViewModel for your Popup? I'd suggest using WindowManager, and creating a ViewModel for the popup - it will be more in-line with what CM already does
I made a WPF app that opens successive windows based on user interaction. For example, the first winodw asks what module the user wants to work on, when a selection is made and a button pushed, a new windows open showing some Vendors and summary counts. Selecting one of those vendors and pushing the Edit button opens another window that shows the details of that Vendor. Clicking a detail and then a button open yet another window where the user can change some numbers etc. Then the user closes that window, picks a different item and edits, or closes that window and picks a different vendor etc. Each window has its own view model currently. I want to get rid of all the layers of windows. Tab Control doesn't seem to be a good option, since the user will have to go through the correct sequences etc. What is the best way to change this to use only one window, and swap out what the user sees in the one window when he, for example, pushes a button to edit etc.?
Personally I prefer to use a <ContentControl /> for my content area, and to swap out the active content based on the user's current "window"
I have an example on my blog that you could look at, but the basic components look like this:
ViewModel:
ObservableCollection<IViewModel> AvailableScreens;
IViewModel ActiveScreen;
ICommand SetActiveScreenCommand;
With some XAML that looks like this:
<ContentControl Content="{Binding ActiveScreen}" />
And I usually use DataTemplates to tell WPF how to draw each ViewModel
<Window.Resources>
<DataTemplate DataType="{x:Type local:ModulesViewModel}">
<local:ModulesView />
</DataTemplate>
<DataTemplate DataType="{x:Type local:VendorsViewModel}">
<local:VendorView />
</DataTemplate>
<DataTemplate DataType="{x:Type local:EditVendorViewModel}">
<local:EditVendorView />
</DataTemplate>
</Window.Resources>
You can use a docking framework such as AvalonDock, which mimics the behavior of Visual Studio.
I'm wondering how to go about creating different views in the main window when a button is pressed. I'm not sure of the correct terminology, so that has hampered my google fu.
I'm thinking that the main viewing area would be a content control, that I could change when a event happens. I made a small drawing to help illustrate my idea / thought.
Any input will be appreciated. Thanks!
It would be really easy to implement this senario using MVVM approach....
Make a ViewModel for you MainView. Then Define Properties of the ViewModels of your UserControls
For Example You have Two UserControl as FirstView and SecondView then make a properties in your viewmodels as ViewToLoadProperty of the type ViewModel (usually called as ViewModelBase)
Set bindings as
<!-- Panel For Hosting UserControls -->
<Border Grid.Column="2">
<ContentControl Name="userControlContentControl"
Content="{Binding Path=ViewToLoadProperty,
}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type ViewModelLayer:FirstViewModel}">
<ViewLayer:FirstView/>
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModelLayer:SecondViewModel}">
<ViewLayer:SecondView />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</Border>
<!-- Panel For Hosting UserControls -->
Then when you click the button Use a command to set the respective ViewModel Intance to this(ViewToLoadProperty) property...(Use RelayCommannds or something like it)
DataTempates would do the rest of the job by selecting the right View according to the right type of ViewModel
YOu can use MVVMLight toolkit if you are implementing MVVM Pattern.. :)
On the right you could have a frame. Then the button would bind a different page or user control to the content of that frame.