Uno Platform initialize Material - uno-platform

I have an app that is using Material extensively. Recently there was an update to Material and looking at the documentation- they have changed how material is initialized. This is the code that I had previously added to my onLaunched method in app.xaml.cs:
this.Resources.MergedDictionaries.Add(new Uno.Material.MaterialColorPalette());
this.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("ms-appx:///MaterialColorPaletteOverride.xaml") });
this.Resources.MergedDictionaries.Add(new Uno.Material.MaterialResources());
In looking at the updated documentation at Uno Platform Material How To
The initialization has changed to the following:
Uno.Material.Resources.Init(this, null);
I tried this and Visual Studio tells me that Resources does not exist in the namespace Uno.Material. I also looked at the sample app example and it was similar:
Uno.Material.Resources.Init(this, new ResourceDictionary { Source = new Uri("ms-appx:///MaterialColorPaletteOverride.xaml") });
Obviously it suffers from the same issue- Resources does not exist- the exact error is the method Resources does not exist in Uno.Material. I have verified the other Uno Packages are at the latest. I do have Xamarin.AndroidX.Lifecycle.LiveData installed as well. Before this update to Material- everything was working as expected. The specific update is to 1.0.0-dev.778. I have reverted to 1.0.0-dev.774 and reverted my code to the three lines I first listed- and it is working again as expected. What should I do so I can implement the new changes?

The Uno.Material library recently introduced a breaking change to the way the Material resources are initialized. Going forward, resource initialization should be done via XAML, similar to the way we initialize <XamlControlsResources /> for WinUI.
The documentation is in the midst of being updated but basically you need to move the initialization to your App.xaml like so:
<Application x:Class="Uno.Themes.Samples.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:material="using:Uno.Material">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Load WinUI resources -->
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<MaterialColors xmlns="using:Uno.Material"
ColorPaletteOverrideSource="ms-appx:///ColorPaletteOverride.xaml" />
<MaterialResources xmlns="using:Uno.Material" />
<!-- Rest of your application resources .... -->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Notice the new <MaterialColors /> and <MaterialResources /> tags. Keep in mind that order is important here and MaterialColors must be initialized before MaterialResources.
The ColorPaletteOverrideSource is optional, but if you are overriding the default Material colors, you would set it here to the path where your new color palette is defined.
You can then go ahead and remove the calls to Uno.Material.Resources.Init from your App.xaml.cs.
You can have a look at the Uno.Material example for a sample of what your app might look like using the new method of resource initialization.

Related

Can I add App.xaml back to a Xamarin.Forms project while using Caliburn.Micro?

The Caliburn.Micro Xamarin.Forms samples (both setup and features illustrate the use of App.cs with no accompanying App.xaml.
I'd like to have an App.xaml file though so I can add in App-level resources into xaml which are now supposed in Xamarin.Forms. Is this possible? How do I do it?
Note, I haven't added one afterwards ever and this is untested, but it should work something like this.
The App.xaml was introduced later into the Xamarin.Forms packages and templates, probably due to the introduction of the app-level resources you are referring to. But basically, the App.xaml isn't different from any other XAML file.
Add a new App.xaml file which looks somewhat like this:
<?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="YourNamespace.YourClass">
<Application.Resources>
<!-- Application resource dictionary -->
</Application.Resources>
</Application>
Note that you need to supply your own namespace in the x:Class="YourNamespace.YourClass" attribute. Now in the same class that you specify here, which should be in your App.cs, make sure the class is marked as partial and the InitializeComponent(); is called in the constructor.
Lastly, make sure that your App.xaml file is marked to be an EmbeddedResource as build action.
In fact that is everything there is to it.
If you want to link your App.xaml and App.xaml.cs file so that they are shown as one node in Visual Studio, open your csproj file in a text-editor and find the <Compile Include="App.xaml.cs" /> node. Edit this to be:
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
While this looks nicer, it's not absolutely necessary.

mvvm light Winforms dll project, how can I load the ViewModelLocator

I am working on a winforms project in c#. The project is an outlook plugin, so no hopes of totally converting to mvvmlight/wpf as it's a winforms dll project.
I am however trying to come up with a way to use MvvM Light and WPF with the ElementHost. The issue I have is getting access to the ViewModelLocator. Normally, this gets added in the App.xaml like this:
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
and is available to a view via :
DataContext="{Binding MyViewModel, Source={StaticResource Locator}}"
In my case, I don't have an App.xaml, nor do I have a program main() method where I can bootstrap the framework (as this is a dll project, not an application). I tried the following in my WPF usercontrol (hosted in an elementhost), but it doesn't work:
DataContext="{Binding MyViewModel, Source={StaticResource Locator}}"
...
<UserControl.Resources>
<ResourceDictionary>
<wpf:ViewModelLocator x:Key="Locator"
d:IsDataSource="True" />
I think it's not working because it's getting declared after its called. This would have been a compromise anyway as I would have needed that code in every view, so I'm kind of glad it didn't work.
Any suggestions how I can get to the ViewModelLocator??
Thanks,
Jeff
So I figured out what to do to solve this. It's not perfect, but it works. In the end, I have no Application to load the bootstrap, so what I really needed was a way to have a view get to the ViewModelLocator so I could databind the view. To do this I made the MyViewModel property static on the ViewModelLocator class and then I changed my DataContext line in the xaml (the view) as follows:
DataContext="{x:Static wpf:ViewModelLocator.MyViewModel}"

Map Stops App from Loading

I have referenced Windows.Phone.Controls and Windows.Phone.Controls.Toolkit.
When adding a map to the screen with via XML:
<phone:PanoramaItem Header="Location">
<maps:Map x:Name="Map" />
</phone:PanoramaItem>
And adding the Capability in the App Manifest:
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Deployment.Parts>
<Capability Name="ID_CAP_MAP" />
</Deployment.Parts>
Whenever I launch the application, it just stays on the Loading screen. I have added the Capability tag in the AppManifest because it fixed the "First chance exception".
Where am I going wrong? Can anyone see an obvious fix?
Edit
if I take the map off, the app loads perfectly fine.
You don't add capabilities in AppManifest.xml. You add them in WMAppManifest.xml. Just open this file, it has a GUI window where you can tick the caps you want under Capabilities tab.

Resource can't be found even when it's present

I've got a really weird issue I can't fix within a Wpf Application. We built a Common Library containing many useful components, one of them is a fancy MessageBox which has the company style. There're three dictionaries that contains nearly everything we require:
<ResourceDictionary Source="/Library;component/Style/Styles.xaml" />
<ResourceDictionary Source="/Library;component/Themes/Globals.xaml"/>
<ResourceDictionary Source="/Library;component/Themes/Controls/Button/Template.xaml"/>
There's a footer for the MessageBox into Globals.xaml, footer uses a template from Template.xaml. It works perfectly but not in one case. I have a main window that dinamically create a plugin and open a window. This window is a regular Window Wpf application loaded through reflection.
Method to open MessageBox is within the same DLL as Resource Dictionaries.
If I call this MessageBox method from the plugin it throws an exception because "Footer" is not found. I set a breakpoint before
window.ShowDialog();
And I see MergedDictionaries is empty into window. Also empty everywhere, only owner of this MessageBox contains those resources. Doing
window.FindResource("key");
Get a null value as expected. However, if I manually copy merged dictionaries using this code lines before open dialog:
foreach (var dict in owner.Resources.MergedDictionaries)
{
window.Resources.MergedDictionaries.Add(dict);
}
And then look for window.FindResource("key") I can see the style, but even though it continues throwing an exception:
Cannot find resource named '{Footer}'. Resource names are case sensitive.
Footer style is used in this line of MessageBox:
<StatusBar Style="{StaticResource Footer}" DataContext="{Binding ElementName=window}"...
I've also tried to declare this resource into the DialogWindow in the library, even when I've not gonna be allowed to change it:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Library;component/Themes/Generic.xaml" />
<ResourceDictionary Source="/Library;component/Themes/Globals.xaml"/>
<ResourceDictionary Source="/Library;component/Themes/Controls/Button/Template.xaml"/>
</ResourceDictionary.MergedDictionaries>
I've been 2 days knocking my head on the monitor and nothing, everything I tried failed. Despite of breaking a monitor of course.
Ran out of ideas...
Regards.
Make sure of the following things
The resource dictionary Build Action is set to Page
Every project that references the Style has a library reference to it (Even if you put the Dictionary in App.xaml if a project that doesn't reference the Resources Library then it wont find it
Place the MergedDictionaries in App.xaml (or in the specific page you want to use them)

MVVM Light + Blend designer view error: Cannot find resource named 'Locator'.

The application runs fine but i could not see my design in the designer view.
It says Cannot find resource named 'Locator'. Obviously, i did not change anything in the code, i just did the data binding using the data binding dialog...
anyone facing the same problem?
There are two known occurrences where this can happen.
If you change to Blend before you built the application, the DLLs are not available yet and this error can be seen. Building the application solves the issue.
There is a bug in Expression Blend where, if you are placing a user control in another user control (or Window in WPF), and the inner user control uses a global resource, the global resource cannot be found. In that case you will get the error too.
Unfortunately I do not have a workaround for the second point, as it is a Blend bug. I hope we will see a resolution for that soon, but it seems to be still there in Blend 4.
What you can do is
Ignore the error when working on the outer user control. When you work on the inner user control, you should see the design time data fine (not very satisfying I know).
Use the d:DataContext to set the design time data context in Blend temporarily.
Hopefully this helps,
Laurent
I've come up with a reasonably acceptable workaround to this problem since it doesn't appear to have been fixed in Blend 4:
In the constructor for your XAML UserControl just add the resources it needs, provided you're in design mode within Blend. This may be just the Locator, or also Styles and Converters as appropriate.
public partial class OrdersControl : UserControl
{
public OrdersControl()
{
// MUST do this BEFORE InitializeComponent()
if (DesignerProperties.GetIsInDesignMode(this))
{
if (AppDomain.CurrentDomain.BaseDirectory.Contains("Blend 4"))
{
// load styles resources
ResourceDictionary rd = new ResourceDictionary();
rd.Source = new Uri(System.IO.Path.Combine(Environment.CurrentDirectory, "Resources/Styles.xaml"), UriKind.Absolute);
Resources.MergedDictionaries.Add(rd);
// load any other resources this control needs such as Converters
Resources.Add("booleanNOTConverter", new BooleanNOTConverter());
}
}
// initialize component
this.InitializeComponent();
}
There may be some edge cases, but its working OK for me in the simple cases where before I'd get a big red error symbol. I'd LOVE to see suggestions on how to better solve this problem, but this at least allows me to animate user controls that otherwise are appearing as errors.
You could also extract out the creation of resources to App.xaml.cs:
internal static void CreateStaticResourcesForDesigner(Control element)
{
if (AppDomain.CurrentDomain.BaseDirectory.Contains("Blend 4"))
{
// load styles resources
ResourceDictionary rd = new ResourceDictionary();
rd.Source = new Uri(System.IO.Path.Combine(Environment.CurrentDirectory, "Resources/Styles.xaml"), UriKind.Absolute);
element.Resources.MergedDictionaries.Add(rd);
// load any other resources this control needs
element.Resources.Add("booleanNOTConverter", new BooleanNOTConverter());
}
}
and then in the control do this BEFORE InitializeComponent():
// create local resources
if (DesignerProperties.GetIsInDesignMode(this))
{
App.CreateStaticResourcesForDesigner(this);
}
Note: At some point in time this stopped working for me and I ended up hardcoding the path to the Styles.xaml because I got frustrated trying to figure out which directory I was in.
rd.Source = new Uri(#"R:\TFS-PROJECTS\ProjectWPF\Resources\Styles.xaml", UriKind.Absolute);
I'm sure I could find the right path with 5 minutes work, but try this if you're at your wits end like I was!
In MyUserControl.xaml, instead of:
DataContext="{Binding Main, Source={StaticResource Locator}
use:
d:DataContext="{Binding Main, Source={StaticResource Locator}
where "d" has been previously defined as:
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
The reason and workaround explained here
http://blogs.msdn.com/b/unnir/archive/2009/03/31/blend-wpf-and-resource-references.aspx
Look at (b) part of the post.
I had a similar problem with a user control resource.
I added this in my usercontrol xaml code:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/GinaControls;component/Resources/GinaControlsColors.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Where GinaControls is the namespace where the control class is declared and /Resources/GinaControlsColors.xaml is the project folder and xaml resource file name.
Hope this helps.
Just add this in your App.xaml.cs at the very beginning
here's my piece of code
[STATThread()]
static void main(){
App.Current.Resources.Add("Locator", new yournamespace.ViewModel.ViewModelLocator());
}
public App(){
main();
}
Make sure the Blend has opened the entire solution and NOT just the single project containing the views. I was right-clicking in Visual Studio and selecting Open In Expression Blend. To my surprize, Blend could not find the solution file, so it only opened the single project.
When I realized this, I launched Blend directly, pointed it to the solution file, and then Blend was able to find the ViewModelLocator in my view.

Resources