I'm new in Xamarin. I want to learn about <Style> tag. I have problem When I start adding tag on App.xaml file,warning message appear.I don't know what mistake that i make. Hope you guys can help me solve this problem.Thank you in advance.
Error Message
App.xaml
<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TravelRecordApp.App">
<Application.Resources>
<!-- Application resource dictionary -->
<ResourceDictionary>
<Color x:Key="blueColor">#1E90FF</Color>
<Color x:Key="whiteColor">#FFFFFF</Color>
<Style>
<Setter Property="BackgroundColor" Value="{StaticResource blueColor}" />
<Setter Property="TextColor" Value="{StaticResource whiteColor}"/>
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
A Style tag must always specify the TargetType. So if, for instance, your style targets labels, you would have to change your code to:
<Style TargetType="Label">
<Setter Property="BackgroundColor" Value="{StaticResource blueColor}" />
<Setter Property="TextColor" Value="{StaticResource whiteColor}"/>
</Style>
By the way, the Xamarin.Forms previewer is a pain in the a**. The error message you're getting probably won't go away even after you fixed it. I had to do a complete clean & rebuild, then open the previewer for a different page, close it and open it again for the page I wanted before it would display anything.
You may be better off not using it.
Another issue could be is that you have some code in the App.xaml.cs in the App() constructor that could be causing the issue as well. For instance I fixed a problem in some code that I inherited that was trying to connect to a database so I fixed it like this:
public App()
{
InitializeComponent();
if (DesignMode.IsDesignModeEnabled)
{
return;
}
// connect to database code here
You can use DesignMode.IsDesignModeEnabled to determine if you are running in the designer or elsewhere. You may also want to check your constructors in your xaml.cs files and see if they are trying to run any code that would cause the designer to throw that exception as well.
If anyone is still having an issue with this, what fixed it for me is going to my NuGet package manager and updating Xamarin Forms to the latest version.
Instantly fixed the issue for me.
Good luck!
Related
I'm trying to add a resource dictionary to a page but I keep getting a designer error in my xaml. The app runs fine with no issue but the designer error bothers me.
Here's how I did it. Both works fin at run time. But it's saying Failed to set "Source". Any clues?
That also gives an error to all the static resource I used from the resource dictionary.
Update:
This is another approach. Instead of directly adding it to the Page's resources, I added it to the Application.Resources still cant resolve the styles. I'm using VS2017 v15.4.4
Steps to reproduce:
List item
Create a new UWP Application Project (App1)
Create a new UWP Class Library (ClassLibrary1)
In ClassLibrary1, add a new ResourceDictionary (Dictionary1.xaml).
In Dictionary1.xaml, add a Style, let's say a button style.
<Style TargetType="Button" x:Name="ButtonStyle1" x:Key="ButtonStyle1">
<Setter Propeprty="Background" Value="Red" />
</Style>
In the ClassLibrary1, add a new BlankPage (BlankPage1)
In the BlankPage1, add a button and use ButtonStyle1
`
In App1, merge the resource dictionary to App.Resources (inside App.xaml).
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionary>
<ResourceDictionary Source="ms-appx:///ClassLibrary1/Dictionary1.xaml" />
</ResourceDictionary.MergedDictionary>
</ResourceDictionary>
</Application.Resources>
Make the BlankPage1 the start page, go to App.xaml.cs and and change MainPage to BlankPage1:
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(BlankPage1), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
}
Run the application. It will run just fine. But the problem is in the designer where it cannot recognize the style from the resource dictionary.
I followed your steps and found a typo and an issue.
The typo: In Style step (Perhaps only in the sample), There is typo in the word 'Proeprty':
<Style TargetType="Button" x:Name="ButtonStyle1" x:Key="ButtonStyle1">
<Style.Setters>
<Setter Property="Background" Value="Red" />
</Style.Setters>
</Style>
The issue in the way you are merging dictionary, it should be using the following syntax:
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
After fixing both issues, Visual studio designer didn't complain about anything.
Did it fix the issue for you? If not then your steps to reproduce aren't complete.
Problem
I am working on an application, and recently I reorganized the file structure as I was adding more parts. Around this time I noticed that at runtime, styles from my App.xaml weren't getting applied. I made a lot of code changes at once before building so I am unsure of what may have changed.
Information
App.xaml remained unchanged before it stopped getting applied.
My program is laid out to have a main <ContentControl> that I bind some views to for some MVVM action. Originally I had all my views for different subfunctions of my program in one Views folder, but individual parts were getting too large so I split them up from this:
<Project>/Models
<Project>/ViewModels
<Project>/Views
to
<Project>/EventEditor/Models
<Project>/EventEditor/ViewModels
<Project>/EventEditor/Views
<Project>/ConfigurationEditor/Models
<Project>/ConfigurationEditor/ViewModels
<Project>/ConfigurationEditor/Views
My UserControl doesn't have any resources or styles of its own and should only be using the ones from App.xaml for now.
I only have 1 App.xaml file and no other files containing styles/dictionaries/etc outside of the individual view XAMLs.
Here is my App.xaml:
<Application x:Class="EventSuite.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:EventSuite"
StartupUri="MainWindow.xaml">
<Application.Resources>
<!-- Global Styles -->
<Style TargetType="ListBoxItem">
<Setter Property="FontSize" Value="14" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="14" />
</Style>
<Style TargetType="Label">
<Setter Property="FontSize" Value="14" />
</Style>
<Style TargetType="Button">
<Setter Property="Margin" Value="2,0,2,0"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="FontSize" Value="14"/>
</Style>
</Application.Resources>
Steps Taken
Clean build/rebuild
Breaking and using Tree Visualizer to investigate (no luck there)
Diffing files/projects. Nothing that I found could be causing this (I don't know exactly what to be looking for)
Questions
Is there a way to debug styles which are being used? I tried the WPF Tree Visualizer and it showed null for Style on my buttons, which is what I would expect since I didn't explicitly set any style.
Could file structure have a role to play? Perhaps App.xaml isn't being read correctly, or it's not being applied correctly. I haven't seen any warnings or indications of failure.
Namespace related? I would hope not...
In summary I am a little lost as to why App.xaml applies in design time and not at runtime. Why could this be happening after some changes to my project. I am lost! Let me know if you need more information or examples.
Turns out it was an issue with App.xaml StartupURI.
My StartupURI was MainWindow.xaml and my App.xaml.cs was as follows:
public partial class App : Application
{
public App()
{
var dialog = new SageCenter.View.MainWindow();
dialog.ShowDialog();
}
}
It was never calling InitializeComponent() on my application, but my window was still getting created. I kept the StartupURI in my App.xaml and changed App.xaml.cs to this to fix it:
public partial class App : Application
{
public App()
{
InitializeComponent();
}
}
The StartupURI="MainWindow.xaml" causes the InitializeComponent() call to instantiate my window.
I'm toying arround a bit with the new VS 2015, and I found two strange behaviors, I really can't explain. Probably you can help me, if this are simple bugs or Im doing something generally wrong:
Í have a simple Project, the Mainwindow has just a Datagrid:
<Grid>
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Header="Test" />
</DataGrid.Columns>
</DataGrid>
</Grid>
In the App.XAML I load a Dictionary in a Subfolder:
<Application.Resources>
<ResourceDictionary Source="Dictionaries\AppDictionary.xaml" />
</Application.Resources>
The Dictionary is looking like this:
<Style TargetType="Grid">
<Setter Property="Margin" Value="10" />
</Style>
Now, as soon as I load the Window, it seems to be frozen forever. I tested some Grid-Properties, but this happens only, when I set the Margin it seems.
I checked the Inheritance from DataGrid or DataGridTextColumn, but they don't seem to inherit from the Grid anyhow.
They second exception:
I need to create a Class in the Dictionaries-Subfolder, otherwise i keep getting the exception:
The type or
namespace name 'Dictionaries' does not exist in the namespace
'WpfApplication3' (are you missing an assembly
reference?)
I didn't work with WPF for a while, but I'm almost certain, I didn't have such problems before, but I might be wrong on this case.
Edit: When I break the Debugging I get the Message:
"Your app has entered a break state, but there is no code to show because all threads where executing external code".
Your information doesn't seem complete but It seems that you are not building the Dictionaries\AppDictionary.xaml file. You need to set its Build Action to Resource.
Also, your dictionary should look like this:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionaries\AppDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
I'm using Resource Dictionaries a lot, but it's getting tedious having to copy and paste them from one Xaml to the other to have them all update. The only way I've seen this done is inheriting a style class, but I do not like the way properties are declared in C# (I prefer the more visual tree syntax of XAML). Is there some way to have one XAML inherit from another? or a method like LoadXaml() that I can call on each Xamarin.Forms.ContentPage I create to inherit from a StylePage?
Here is my style xaml page:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Demo.StylePage">
<!-- Shared Properties -->
<ContentPage.Resources>
<ResourceDictionary>
<!-- TitleBar Styles -->
<Style x:Key="TitleBarStyle" TargetType="StackLayout">
<Setter Property="BackgroundColor" Value="#5db3d6"/>
<Setter Property="Padding" Value="15,6"/>
<Setter Property="HeightRequest" Value="44"/>
</Style>
<Style x:Key="TitleBarHeaderStyle" TargetType="Label">
<Setter Property="TextColor" Value="White"/>
<Setter Property="VerticalOptions" Value="CenterAndExpand"/>
<!-- <Setter Property="FontSize" Value="18"/>-->
<Setter Property="HorizontalOptions" Value="FillAndExpand"/>
</Style>
<Style x:Key="EmptyFrameStyle" TargetType="Frame">
<Setter Property="HasShadow" Value="false"></Setter>
<Setter Property="BackgroundColor" Value="Transparent"></Setter>
<Setter Property="Padding" Value="0,0"></Setter>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
</ContentPage>
How could I load this resource dictionary from another file? Thank you for your time, Sergei.
ContentPages support inheritance. You can always define one BasePage, implement your resources there, and then have each new ContentPage inherit it. While I've never done this with inheriting xaml, I have used to share analytics, logging, etc. in my BasePage's code-behind (as shown below).
I'd suggest trying a similar approach and just instantiating your resource dictionary in your BasePage.
BaseFormPage:
public class BasePage : ContentPage
{
public BasePage () : base () { }
protected override void OnAppearing ()
{
base.OnAppearing ();
AnalyticsApi.LogPageView ();
AnalyticsApi.LogEvent(Title + " Page Loaded");
}
}
ChildFormPage:
<?xml version="1.0" encoding="UTF-8"?>
<local:BasePage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyApp;assembly=MyApp"
x:Class="MyApp.LoginPage"
Title="{x:Static local:Strings.SignIn}"
BackgroundColor="{x:Static local:Colors.ThemeQuaternary}">
<StackLayout>
...
</StackLayout>
</local:BasePage>
You can replace your App.cs with a XAML/cs combo as shown here
The resources defined in your App.xaml will be available for every view loaded in your app.
Make sure your App.xaml file has a build action of "Embedded Resource". Alternatively you can add it as a ContentView with XAML from the UI and then replace ContentView with Application
App.xaml
<Application
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="WorkingWithAppResources.App">
<Application.Resources>
<ResourceDictionary>
<Style x:Key="labelStyle" TargetType="Label">
<Setter Property="TextColor" Value="Green" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
App.xaml.cs
public partial class App : Application
{
public App ()
{
InitializeComponent ();
MainPage = YourContentPage(); // change as required
}
}
In Xamarin.Forms, you can declare resources on every VisualElement. You then access those resources using either {StaticResource} or {DynamicResource}.
The resolution rules applied are roughly as follows:
for {StaticResource}:
Look in this VisualElement.Resources or any of its parent in the same XAML file
Then look in Application.Current.Resources
for {DynamicResource}:
Look in this VisualElement.Resources or any of its parent, even the ones not defined in the same XAML file, and up to the Application.Resources
note that {DynamicResources} supports adding resources later, or changing parents
To answer your question, you can indeed define your Styles in a base class in XAML and use XAML inheritance, or add all your resources to your Application class. If you don't have a XAML file for your Application, just add one, and call InitializeComponents() from the Application constructor.
I have a WPF application that should be used on a touch screen. I have been asked to play a sound when a button is pressed on the screen, for the whole application.
My idea was to create a style to do this, include the resource dictionnary in my app.It works quite well.
However, this style is in a separate DLL and I would like my main application to change the path of the sound file (BoutonClickSound Url below). But I could not find a way to do it.
I have tried several ugly things like :
System.Windows.Application.Current.Resources.MergedDictionaries[0]["BoutonClickSound"] = new Uri(m_MainVM.ButClickSoundPath);
System.Windows.Application.Current.Resources.MergedDictionaries[0].MergedDictionaries[0]["BoutonClickSound"] = new Uri(m_MainVM.ButClickSoundPath);
But none of them seems to work...
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=PresentationFramework"
xmlns:sys="clr-namespace:System;assembly=System">
<sys:Uri x:Key="BoutonClickSound">c:\buttonclick.wav</sys:Uri>
<Style TargetType="{x:Type FrameworkElement}" x:Key="SoundButton">
<Style.Triggers>
<EventTrigger RoutedEvent="PreviewMouseDown">
<SoundPlayerAction x:Name="SoundPlayer" Source="{DynamicResource BoutonClickSound}" />
</EventTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type primitives:Selector}" x:Key="SoundSelectionChange">
<Style.Triggers>
<EventTrigger RoutedEvent="SelectionChanged">
<SoundPlayerAction x:Name="SoundPlayer" Source="{DynamicResource BoutonClickSound}" />
</EventTrigger>
</Style.Triggers>
</Style>
Any idea how to do this ?
Thank you.
Just declare a local resource with the same key.
If you want it globally in your application, you can add it to a MergedDictionary after you include the MergedDictionary from your library.
Add another entry like this:
<sys:Uri x:Key="BoutonClickSound">c:\differentfile.wav</sys:Uri>
And it should cause your style to use that file instead.
Edit:
To set the resource in the code-behind, first you must add it to the local resource dictionary:
Resources.Add("BoutonClickSound", new Uri("your uri here"));
After you add it, if you want to later change it, you can't re-add it, you have to modify it:
Resources["BoutonClickSound"] = new Uri("your uri here");