Im trying to print visual (or anything related) with pagination from a WPF element. I'm using a MVVM Pattern development.
This is my visual layout. Where the user can scroll to view the pages.
<ScrollViewer>
<StackPanel x:Name="Wrapper">
<StackPanel x:Name="PageOne" />
<StackPanel x:Name="PageTwo" />
</StackPanel>
</ScrollViewer>
The visual is passed via a Command Binding on a button.
<Button Command="{Binding PrintCommand}" CommandParameter="{BindingElementName=Wrapper}"
The visual is passed to the print Method.
PrintDialog newDialog = new PrintDialog();
newDialog.PrintVisual(MyVisualName, "Printing is Fun!");
I would like to paginate the two pages (and more), and also scale the visual to the paper, Whilst holding true to MVVM style.
Thanks.
In the end i used Flow Inline Flowdocument.
<FlowDocumentScrollViewer>
<FlowDocument x:Name="EntirePage">
<Section>
<BlockUIContainer>
</BlockUIContainer>
</Section>
</FlowDocument>
</FlowDocumentScrollViewer>
Every control within the BlockUIContainer is printed. (A Lot of page size and margin fiddling is required to get pagination working perfectly) Section/ BlockUI does pagination somewhat automatically - so for me page one was one BlockUi and Page two was another - Comment/Ask for more info
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="{Binding PrintCommand}" CommandParameter="{Binding ElementName=EntirePage}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
I passed the FlowDocument via a command Parameter.
printCommand = new RelayCommand(p => PreparePrint((FlowDocument)p));
(pageVisual being the flow document passed via the command param)
Then between a few of methods i get to;
IDocumentPaginatorSource idocument = pageVisual as IDocumentPaginatorSource;
printDialog.PrintDocument(idocument.DocumentPaginator, "Printing Machine : " + Machine.Serial);
If you are confused and need help (much like i was) then don't hesitate to comment/ask questions.
Related
I would like to know if there's a way to implement a responsive Master/Detail page using only one. What I want is something exactly like the Project here:
https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlMasterDetail
Except for the detail that instead of using two pages and navigating from one to another I would only use one page.
Is there a way to do it? If so, could you link me a working example?
Except for the detail that instead of using two pages and navigating from one to another I would only use one page.
After going through the project, I found it implemented a responsive master/detail experience based on the size of the screen. When the app view is sufficiently wide, the master list and detail view should appear side by side in the same app page. However, on smaller screen sizes, the two pieces of UI should appear on different pages, allowing the user to navigate between them. From my point of view, I think this is a good solution for implementing a responsive master/detail experience.
Is there a way to do it? If so, could you link me a working example?
The project already shows how to implement responsive Master/Detail in UWP using only one page, but it implements more and that makes it a little complex to understand. So I make a simple example which directly shows how to implement responsive Master/Detail in UWP using only one page.
Following is the main steps:
First, create a ListView to show master information in xaml page:
<!--Master VIEW-->
<ListView x:Name="ItemListView" Margin="0,0,0,8">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel HorizontalAlignment="Left" Margin="10,8,0,0">
<TextBlock Text="{Binding Title}" FontSize="25" Width="400" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Second, specify the details view that shows the details item related to the selection on the master list in the same xaml page:
<!--DETAILS VIEW-->
<StackPanel Grid.Column="1" x:Name="ContentPanelDetail" Margin="10,0,0,0" DataContext="{Binding SelectedItem, ElementName=ItemListView}">
<TextBlock Text="{Binding Title}" MaxHeight="80" FontSize="30" HorizontalAlignment="Left" Margin="0" />
<TextBlock x:Name="DetailTextBlock" FontSize="35" Text="{Binding Content}" HorizontalAlignment="Left" Margin="0,18,40,0" Width="500" Height="Auto" TextWrapping="Wrap" />
</StackPanel>
Then, set the ItemsSource for the ListView in code behind:
public MainPage()
{
this.InitializeComponent();
//set the ItemsSource for the ListView
ItemDetails messageData = new ItemDetails();
ItemListView.ItemsSource = messageData.Collection;
ItemListView.SelectedIndex = 0;
}
Last but not least, put Master View and Details View into a SplitView and use VisualStateManager to make it more responsive.
Here is the simple example and the output for your reference.
To implement Master/Detail pattern on your page, you don't have to do it yourself. Instead you can use MasterDetailsView control from UWP Community Toolkit, it does a lot work for you + it is well documented.
Note: For details section of the control, do not set background to null (NoSelectionContent will be visible).
I am creating Windows Phone 8 silverlight application and i am using map control with toolkit MapExtensions to bind the pins on the map. But when I navigate away from map screen or come back to this screen it takes normally 2 to 3 sec to load this page. Where as when application is navigating between other non map pages it is fast. How can i improve application performance regarding map load and unload time while navigation. Here is the map control code I am using:
<maps:Map x:Name="map"
Center="{Binding CenterLocation,
Mode=TwoWay}"
CacheMode="BitmapCache"
ColorMode="Light"
Background="White"
>
<i:Interaction.Triggers>
<i:EventTrigger EventName="ResolveCompleted">
<i:InvokeCommandAction Command="{Binding MapResolveCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<tool:MapExtensions.Children>
<tool:UserLocationMarker GeoCoordinate="{Binding CurrentLocation,Mode=TwoWay}"
Width="50"
Height="50"
Style="{StaticResource LocationMapMarker}">
</tool:UserLocationMarker>
<tool:MapItemsControl Name="mapItems">
<tool:MapItemsControl.ItemTemplate>
<DataTemplate>
<tool:MapChildControl GeoCoordinate="{Binding ItemLocation, Converter={StaticResource LocationToGeoCoordinateConverter}}">
<tool:MapChildControl.Content>
<Image
Source="{Binding ItemId,
Converter={StaticResource ImageConverter}}" />
</tool:MapChildControl.Content>
</tool:MapChildControl>
</DataTemplate>
</tool:MapItemsControl.ItemTemplate>
</tool:MapItemsControl>
</tool:MapExtensions.Children>
</maps:Map>
This is to be expected. The map control is a pretty heavy control as there is a lot of moving parts to it. In addition to that, by putting it on a page, every time you move to the page the Map is recreated. What you can do is create a single map and reuse it across all the pages. I wrote a blog post on how to do this for Windows Store apps here: https://rbrundritt.wordpress.com/2014/10/24/be-smooth-optimize-bing-maps-in-multipage-windows-store-apps-javascript/
This was for a JavaScript application so this only shows the concept and would take a decent amount of work to port over.
I heed to create wizard and in the wizard I have tab control which have to call to the user control according to the context,I need to create the wizard which will able to invoke
different pages according to the user selection ,currently I call to the pages as follows which I think is not the right way,any Idea how should I do it via code (not in the xaml )i.e. according to some decision invoke the suitable page to the tab control.
this is the xaml:
<Border Grid.Column="1" Name="MainBorder">
<TabControl x:Name="MainTabControl" Height="638" VerticalAlignment="Bottom">
<TabItem Visibility="Collapsed" >
<Frame Source="page1.xaml" />
</TabItem>
<TabItem Visibility="Collapsed" >
<Frame Source="page2.xaml"/>
</TabItem>
<TabItem Visibility="Collapsed" Header="Step 3">
<TextBlock Text="Page 3"/>
</TabItem>
<TabItem Visibility="Collapsed" Header="Step 4">
<TextBlock Text="Page 4"/>
</TabItem>
</TabControl>
</Border>
UPDATE
I was tried in the main window like the following without success
create new tab by code and add to it the page 1 and then add it to the MainTabControl
TabControl tabControl = new TabControl(new Page1());
MainTabControl.add..
.
there is no add in the main tab control
For this scenario, I would use a Frame rather that tabs. The frame allows you to manage the flow of it's content via the NavigationService. You can use Uri's to display a page via the Frame.Source property, or a FrameworkElement via the Frame.Content property. Both are DependencyProperties and can therefore be bound to.
Paul Stovel wrote an excellent blog on this called WPF Navigation. Everything you need to create a wizard from a frame can be found in this blog, including passing values between pages and templating of the Frame to simply handle the display of navigation buttons.
I would agree with Mark, it is a lot easier to use NavigationWindows than TabControls.
I've worked on a lot of interfaces like this and written up some of the basic things with,
WPF Wizards, Part 1
WPF Wizards, Part 2
Then more recently I worked out how to get the styling just right
Styling Wizards
In fact I've released the styling and examples as open source at
WinChrome
There is some simple example code including use of a navigation list to the left with,
WinChrome.Win7Demo
Hope this helps
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 have another question with windows phone 7 dev. I'm creating listbox with items and one textblock, which is something like link to another page. Each link will have another "page" variable value.
<TextBlock Tap="TextBlock_Tap" Foreground="#FF40AA2F" Text="View details">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<ec:NavigateToPageAction TargetPage="/details.xaml?page={Binding Index}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
But it doesn't work with current value in targetpage, because Visual Studio taking it like normal string. How can I embed this binding in page variable? Thank you
Try using StringFormat:
<ec:NavigateToPageAction TargetPage="{Binding Path=Index, StringFormat='/details.xaml?page={0}'}" />
Do the navigation, not on a trigger but in the code behind of the MouseLeftButtonDown event of the Text Block and extract the target page from the current selection of the listbox.