Page background in frame not working - xaml

I have main page:
<Page >
<Grid>
<SplitView PaneBackground="Transparent" x:Name="mySplitView" DisplayMode="Overlay" IsPaneOpen="{Binding IsOpenMenu, Mode=TwoWay}" OpenPaneLength="320">
<SplitView.Pane>
...
</SplitView.Pane>
<SplitView.Content>
<Grid>
<Frame x:Name="frame"
Margin="0,0,0,0">
<Frame.ContentTransitions>
<TransitionCollection>
<NavigationThemeTransition>
<NavigationThemeTransition.DefaultNavigationTransitionInfo>
<EntranceNavigationTransitionInfo/>
</NavigationThemeTransition.DefaultNavigationTransitionInfo>
</NavigationThemeTransition>
</TransitionCollection>
</Frame.ContentTransitions>
</Frame>
</Grid>
</SplitView.Content>
</SplitView>
</Grid>
</Page>
In Frame i load other page. Example Page1.
In Page1 set background:
<Page Background="Red" >
</Page>
And this not working? Background is not Red. Why?

Your second Page needs content. Try this:
<Page Background="Red">
<Grid/>
</Page>
Typically for Pages and UserControls, you would actually set the Background of the content root element instead of the element itself:
<Page>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
</Grid>
</Page>
EDIT
I ran the app in the mobile emulator instead of the local machine and can reproduce your issue. All I can suggest is that you set the background on the content root element instead of the page, as I mentioned above.

Related

XAML Master / Template pages with MVVM

Is there a way to create master / template pages in XAML (for UWP applications)?
The problem I'm trying to solve:
I have an application with a lot of similar sites, where only the content changes slightly but not the Buttons and the Layout. Example:
<Page
DataContext="{Binding WebpageViewModel, Source={StaticResource Locator}}">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Edit Webpage" Style="{StaticResource BigTexBlock}" />
<ScrollViewer Style="{StaticResource ContentScrollViewer}" Grid.Row="1" VerticalScrollMode="Enabled">
<StackPanel Margin="10,0">
<webpage:EditWebpage DataContext="{Binding }" />
</StackPanel>
</ScrollViewer>
</Grid>
</Grid>
<Page.BottomAppBar>
<CommandBar>
<CommandBar.PrimaryCommands>
<!-- more buttons -->
<AppBarButton IsCompact="True" Command="{Binding SaveEntryCommand}" Icon="Save" Label="Save" />
</CommandBar.PrimaryCommands>
</CommandBar>
</Page.BottomAppBar>
</Page>
Only three parts of this template will change; the ViewModel in the DataContext, the Text of the TextBlock, and the UserControl which contains the editable fields.
As this is an application with a lot of CRUD happening with simple Entities the amount of code to be repeated over and over again is a lot if I keep "solving" the problem like this. In the separated business logic I could avoid this problem with inheritance, but I'm struggling to find a elegant solution in XAML. 
Is there a way to refactor this so I may have a "Template Page"?
I like how for example twig has solved this problem: http://twig.sensiolabs.org/. You define a master/template page and override parts of it in the children templates.
Important to me is that
I don't break the MVVM pattern.
I don't want to hide/show UserControls in one "Main" XAML as the amount of different entities may become quite large
I want navigation happening between the pages that the user sees the expected animations, and it does not break the separated view code I already have
There isn't a master page or template mechanism that other technologies, like MVC, have. But you can use frames and navigation to do what you're looking for.
You could keep the page defined the way you currently have it. All of the fixed elements on the page are in the layout. Now instead of using a UserControl for your specific edit UI, replace that with a frame.
<StackPanel Margin="10,0">
<Frame Name="EditFrame" DataContext="{Binding }" />
</StackPanel>
Now when you navigate to the Main Edit page, also pass the type for the view you want in the frame. Then on your OnNavigatedTo override for the main page, you can navigate the frame to the view type as the parameter.
You can also use the EditFrame to page through multiple editing pages, like if you had a wizard UI with Next and Previous buttons, without leaving the main page.
You can either do this in your OnNavigatedTo method or modify your NavigationService to be able to handle this behavior.
I have solved this problem with the approach suggested by https://stackoverflow.com/a/43170663
my NavigationService
//get the current frame
var frame = (Frame)Window.Current.Content;
//navigate to the generic AddEntry page
frame.Navigate(typeof(AddEntryPage), new NavigationParameter() { /* set props needed */ });
my xaml (my "master page") looks now like this (using a Frame now):
<Page
x:Class="Famoser.Bookmarked.Presentation.Universal.Pages.Entry.Webpage.AddEntryPage"
mc:Ignorable="d"
d:DataContext="{Binding WebpageViewModel, Source={StaticResource Locator}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock x:Name="Title" Grid.Row="0" Text="Add "/>
<ScrollViewer Grid.Row="1">
<StackPanel Margin="10,0">
<Frame x:Name="EntryFrame" />
</StackPanel>
</ScrollViewer>
</Grid>
<Page.BottomAppBar>
<CommandBar>
<CommandBar.PrimaryCommands>
<!-- more app buttons -->
<AppBarButton IsCompact="True" Command="{Binding SaveEntryCommand}" Icon="Save" Label="Save" />
</CommandBar.PrimaryCommands>
</CommandBar>
</Page.BottomAppBar>
</Page>
and in the code behind in the navigation event I set the properties passed by my NavigationService
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.Parameter is NavigationParameter pm)
{
DataContext = SimpleIoc.Default.GetInstance(pm.ViewModelType);
Title.Text = "Add " + pm.Name;
EntryFrame.Navigate(pm.EditFrameType);
}
}
the full project in on github: https://github.com/famoser/Bookmarked

How to add image and keep text on PivotItem

This question shows how to substitute PivotItem headers text with images, but I wish to have both (plus, the text should be a variable).
The goal is to replicate the following Navigation model:
(source: s-msft.com)
Is it possible to adapt this simple XAML to achieve both text and image? If not, how to do it?
<Page
x:Class="Lenny.Windows.Views.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:Lenny.Windows.Views"
mc:Ignorable="d">
<Page.BottomAppBar>
<CommandBar>
<CommandBar.Content>
<Grid/>
</CommandBar.Content>
<AppBarButton Icon="Accept" Label="appbarbutton"/>
<AppBarButton Icon="Cancel" Label="appbarbutton"/>
</CommandBar>
</Page.BottomAppBar>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Pivot>
<Pivot.HeaderTemplate>
<DataTemplate>
<Image Source="{Binding}"></Image>
</DataTemplate>
</Pivot.HeaderTemplate>
<PivotItem Header="/Assets/LockScreenLogo.scale-200.png" >
<Grid />
</PivotItem>
<PivotItem Header="/Assets/LockScreenLogo.scale-200.png">
<Grid/>
</PivotItem>
<PivotItem Header="/Assets/LockScreenLogo.scale-200.png">
<Grid/>
</PivotItem>
</Pivot>
</Grid>
</Page>
If you are using MVVM you can use a property from your ViewModel and add a textblock in the header template to make a binding with this property and you can change this value from your ViewModel.
I said this because you need the text needs to be variable.
If you are not using MVVM pattern you need to use the Binding Approach
https://msdn.microsoft.com/en-us/library/windows/apps/mt269383.aspx
in xaml you need to add a stackpanel with orientation = horizontal and add your text and your image inside all of them in your header template

WPF Button Image Disappears At Runtime

I have written the user control below and I want to display a clock image on the button control. The image has BuildAction set to Resource. It shows up perfect in the XAML design screen, but when I run the application the button is blank. What am I doing wrong?
<UserControl x:Class="App_Process_Admin.User_Controls.TimePicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="150">
<UserControl.Resources>
<ResourceDictionary>
<Image x:Key="ClockImage" Source="Icons/Clock.png"/>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="180" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60*" />
<ColumnDefinition Width="20*" />
</Grid.ColumnDefinitions>
<TextBox Grid.Row="0" Grid.Column="0" Name="TimeField" Text="" />
<Button Grid.Row="0" Grid.Column="1" Content="{StaticResource ClockImage}" Click="SetTime_Click" />
<local:ClockPopUp x:Name="ClockPopUp1" Grid.Row="1" Grid.Column="0" Visibility="Hidden"></local:ClockPopUp>
</Grid>
</UserControl>
I had the same problem, i resolve it this way (in visual studio 2019, wpf application) :
put your images in your project in a folder
Create an image in xaml and put your source
At this point for me the images are displayed in the design window but not at the runetime
Access to your image in your project with the solution explorer
Select each image and open the property window
Set "Generation action" to "Resource" and "Copy in the repository" To "always copy"
I have done that and i can see my images at runtime :)
PS : sorry for my english, i'm french
Image is a control. If you add it to resources his way, it'll only be displayed in the last place it's added to and will disappear from all previous places. You can fix this by adding x:Shared=False:
<Image x:Key="ClockImage" x:Shared="False" Source="Icons/Clock.png"/>
This way, a new Image control will be created every time it's requested.
Alternatively, you can create a button style with Image in its ContentTemplate and add BitmapImage to the resources directly:
<BitmapImage x:Key="Bitmap" UriSource="Icons/Clock.png"/>
<Style x:Key="ButtonImage" TargetType="Button">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{TemplateBinding Content}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Now you can create buttons with images this way:
<Button Content="{StaticResource Bitmap}" Style="{StaticResource ButtonImage}"/>
Image controls will be created by the framework based on the template.
In my case, it was needed to first add the images into project, by drag-and-drop'ing them into the folder where your .xaml is in solution explorer.
Then, i added to .xaml:
<Window.Resources>
<BitmapImage x:Key="Icon" UriSource="Images/Image.png"/>
</Window.Resources>
<Button x:Name="SomeButton" Background="Gray">
<Image Source="{StaticResource Icon}"/>
</Button>
And that's it.
Also, if you have complicated project with many folders, you can use ../ in UriSource to go up a folder from the current, where .xaml file is located

How to set DataContext for all Page or for AppBarButton

I have XAML page that looks like:
<Page
xmlns:vm="using:domain.viewmodels">
<Page.Resources>
<vm:MainPageViewModel x:Name="MainPageVm"/>
</Page.Resources>
<Grid DataContext="{Binding Source={StaticResource MainPageVm}}">
<Button Command={Binding QuitCommand, Mode=TwoWay}"/>
</Grid>
<Page.BottomAppBar>
<CommandBar IsOpen="True">
<AppBarButton Label="Quit" Command={Binding QuitCommand, Mode=TwoWay}"/>
</CommandBar>
</Page.BottomAppBar>
</Page>
If I press the Button – the Command was executed.
If I press the AppBarButton – the Command was not executed.
I get that the reason is that I have set DataContext for Grid only, but not for BottomAppBar. But I don't know how to set DataContext for all Page.
I have tried this code, but it doesn't work because I have declared MainPageVm below:
<Page
DataContext="{Binding Source={StaticResource MainPageVm}}"
xmlns:vm="using:domain.viewmodels">
<Page.Resources>
<vm:MainPageViewModel x:Name="MainPageVm"/>
</Page.Resources>
I thought I can set DataContext for CommandBar. I don't like this solution, as I need to set DataContext twice for the Page, but even this solution doesn't work:
<Page.BottomAppBar>
<CommandBar IsOpen="True" DataContext="{Binding Source={StaticResource MainPageVm}}">
<AppBarButton Label="Quit" Command={Binding QuitCommand, Mode=TwoWay}"/>
</CommandBar>
</Page.BottomAppBar>
Why?
Instead of using Resources, set the DataContext directly:
<Page
xmlns:vm="using:domain.viewmodels">
<Page.DataContext>
<vm:MainPageViewModel x:Name="MainPageVm"/>
</Page.DataContext>
Your bindings become then:
<Grid>
<Button Command={Binding QuitCommand}"/>
</Grid>
<Page.BottomAppBar>
<CommandBar IsOpen="True">
<AppBarButton Label="Quit" Command={Binding QuitCommand}"/>
</CommandBar>
</Page.BottomAppBar>
It's often simpler to declare your DataContext in code-behind:
public YourPageClass()
{
InitializeComponent();
this.DataContext = new MainPageVM();
}

Adding A Background Image In XAML

I am very new to XAML code, but I want to try and code a personal program. I have started with XAML but anything I add does not show up. Here is my code:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button Content="Home" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="7,725,0,0" Height="36" Width="91" BorderBrush="Orange" Foreground="Orange" FontFamily="BankGothic Md Bt"/>
<Image HorizontalAlignment="Left" Height="768" VerticalAlignment="Top" Width="1366" Source="C:/Users/Flynn/Desktop/BG.gif" Visibility="Visible"/>
</Grid>
</Page>
The button nor the image is showing up when I run the program. Can someone point me in the right direction? Thanks for your help!
To set a background to a grid, just keep your image in Images folder and add this code inside grid
<Grid.Background>
<ImageBrush Stretch="Fill" ImageSource="..\Images\background.jpg" AlignmentY="Top" AlignmentX="Center"/>
</Grid.Background>
Please try this code.It works
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Button Content="Home" HorizontalAlignment="Left" VerticalAlignment="Top" Height="36" Width="91" BorderBrush="Orange" Foreground="Orange" FontFamily="BankGothic Md Bt"/>
<Image Stretch="None" VerticalAlignment="Center" HorizontalAlignment="Center" Source="Images/super.jpg"/>
</Grid>
You should define the background property like this
You must add in to App.xaml (for color resource)
<Application.Resources>
<SolidColorBrush x:Key="ApplicationPageBackgroundThemeBrush" Color="BlueViolet"/>
</Application.Resources>
Image source have to be in your solution (application)