WPF Button Image Disappears At Runtime - xaml

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

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

Page background in frame not working

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.

Customize Windows Phone 8.1 message dialog

I want to customize my message dialog as shown in following figure
How do I perform that I have prepared xaml for this
<StackPanel Name="rootStackPanel" Height="Auto" Background="#363636" VerticalAlignment="Top">
<StackPanel Margin="10">
<StackPanel Margin="0,0,0,10" Orientation="Horizontal">
<TextBlock x:Name="HeadingText" x:FieldModifier="public" Style="{StaticResource ApplicationMessageBoxHeadingStyle}" Text="Alert" />
<Image Margin="10,05,0,0" Source="/Assets/Images/alert.png" Width="35"></Image>
</StackPanel>
<TextBlock x:FieldModifier="public" x:Name="ContentText" Style="{StaticResource ApplicationMessageBoxErrorStyle}" Text="Pease enter a valid plate number" />
<Button x:FieldModifier="public" Name="OkButton" Margin="0,20,0,0" Padding="0" HorizontalAlignment="Left" Content="Ok" Style="{StaticResource ApplicationThemeButtonStyle}"/>
</StackPanel>
</StackPanel>
The exact look you have there is non-standard, and if you want that exact thing you'll need to write some custom code. If the important part is the icon in the alert title then this is pretty easy with a ContentDialog.
The MessageDialog isn't customizable, but the ContentDialog is. There is a template to add a new ContentDialog to your project with the Add.New Item... menu.
Once you have your ContentDialog files you can customize the template to title its button "OK":
<ContentDialog
x:Class="MyApp.AlertDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Alert"
PrimaryButtonText="OK"
PrimaryButtonClick="ContentDialog_PrimaryButtonClick"
>
And include your alert.png along with the Title in the title template. A more advanced version would allow binding different icons for different purposes.You could also fill a path instead of drawing a png so the icon will scale more easily.
<ContentDialog.TitleTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}" Foreground="{ThemeResource PhoneAccentBrush}"/>
<Image Source="/Assets/Images/alert.png" />
</StackPanel>
</DataTemplate>
</ContentDialog.TitleTemplate>
And then include the rest of the contents in the ContentDialog's Xaml:
<StackPanel>
<TextBlock x:FieldModifier="public" x:Name="ContentText" Style="{StaticResource ApplicationMessageBoxErrorStyle}" Text="Pease enter a valid plate number" />
</StackPanel>
This will put the OK button in its standardized location at the bottom right. If you want to include it with the text you can stick it in your StackPanel like in your sample code and not set the PrimaryButtonText on the ContentDialog.
Create a Usercontrol in the project.
Put the entire xaml code in the Usercontrol.
Now you can use this Usercontrol as a popup wherever you want to use it.
Popup msgpopup = new Popup( );
msgpopup.child = new CustomisedMessageDialogControl(); //name of ur Usercontrol
And to open this Dialog simply,
msgpopup.IsOpen = true;

ContentDialog's buttons are not shown in a Windows Phone 8.1 app if the BottomAppBar is defined

I would like to show a ContentDialog on first launch of my app, to show the EULA to the end user.
It seems that if an AppBar is defined in the calling page the two buttons in the dialog are not visible, an empty area with the same size of the command bar area defined in the calling page, is shown instead.
This is the markup on the ContentDialog:
<ContentDialog
x:Class="MyApp.EulaPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp.Pages"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="TERMS OF USE"
PrimaryButtonText="i agree"
SecondaryButtonText="cancel"
PrimaryButtonClick="OnAgreeButtonClick"
SecondaryButtonClick="OnCancelButtonClick">
<Grid x:Name="ContentPanel" Margin="0,0,0,0" >
<Grid.RowDefinitions>
<RowDefinition Height="524" />
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0" Margin="0,0,0,2" >
<RichTextBlock IsTextSelectionEnabled="False" TextAlignment="Left" TextIndent="0" FontSize="14" FontFamily="Segoe WP" >
</RichTextBlock>
</ScrollViewer>
</Grid>
The GridRowDefinition has a fixed hight, because the text in the RichTextBlock needs to be scrolled.
I have prepared a sample project that can be found here. The zip file contains also a screenshot showing how I see the dialog.
I had the same problem and I have solved it by modifying/removing Height/Width and Margins of the Contentdialog

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)