I am trying to start a MVVM pattern and I have this structure:
App.xaml:
<Application x:Class="StereoVisionApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:StereoVisionApp"
StartupUri="MainView.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<local:MainViewModel x:Key="StereoVisionApp.MainViewModel"/>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
MainViewModel.cs:
namespace StereoVisionApp.ViewModels
{
class MainViewModel
{
public MainViewModel()
{
}
}
}
I have an error on this line:
<local:MainViewModel x:Key="StereoVisionApp.MainViewModel"/>
Says:
The name "MainViewModel" does not exist in the namespace
"clr-namespace:StereoVisionApp". StereoVisionApp C:\Users\Me\source\repos\StereoVisionApp\StereoVisionApp\App.xaml
I have tried restarting million times. any help?
In Visual Studio, when you create a new folder in the project at creates a new namespace named projectname.foldername by default. (in your case: StereoVisionApp.ViewModels). All the files inside it automatically takes that namespace.
You can either:
Change the namespace in MainViewModel.cs
or
Add the new namespace to App.xaml like this:
add this in Application header in App.xaml
xmlns:vm="clr-namespace:StereoVisionApp.ViewModels"
Then use it like this:
<vm:MainViewModel x:Key="StereoVisionApp.MainViewModel"/>
Also note that the x:Key value is a string of your choice (doesn't have to be an exact location, so you can actually write:
<vm:MainViewModel x:Key="mainViewModel"/>
The x:Key value is for future reference only.
Related
I want to achieve themes in my WPF program.
I stored the color in the database and then load it into MergedDictionaries.
Here are my codes:
<Application x:Class="Test"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
And here are code-behind:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Resources;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Resources;
namespace Test
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public App()
{
ChangeTheme("Dark");
}
public ResourceDictionary ThemeDictionary
{
get { return Resources.MergedDictionaries[0]; }
}
public void ChangeTheme(string ThemeName)
{
Resources.MergedDictionaries.Clear();
Resources.MergedDictionaries.Add(new ResourceDictionary());
///some logic to load color from database
ThemeDictionary.Add("NormalBackground",new SolidColorBrush(Colors.Red));
}
}
}
And here are sample of front-end:
<Window x:Class="Test"
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:local="clr-namespace:Test"
mc:Ignorable="d"
Height="450" Width="800">
<Grid Background="{StaticResource NormalBackground}">
</Grid>
</Window>
After the program ran. VS reports error that cannot find StaticResource "NormalBackground".
Whereas, if I add an exist ResourceDictionary into the MergedDictionaries, all works well.
What's wrong with my code? Thank you.
You are calling "ChangeTheme("Dark")" too early. It should be called from within OnStartup in App.xaml.cs. I guess that the resource dictionaries defined in the xaml (which is empty in your case) will overwrite everything you put in there by code in your constructor.
public App()
{
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
ChangeTheme("Dark");
}
Also, you can remove the inner part of your MergedDictionaries from you App.xaml
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
According to the logic of work in the current implementation, you first set your dictionary in the App constructor. After that, the XAML is initialized. Upon XAML initialization, the <ResourceDictionary> tag creates a new dictionary and stores it in App.Resources. This action removes the instance you created in the constructor.
Therefore, when the UserControl is called, the App only has an empty dictionary in which your resource does not exist.
For your implementation to work properly, you should remove the <Application.Resources> section entirely from the XAML.
<Application x:Class="Test"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test"
StartupUri="MainWindow.xaml">
<!-- <Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>-->
</Application>
As others have suggested, replacing StaticResource with DynamicResource is not a solution, as there is no resource itself with the specified key.
DynamicResource can help if you replace the resource pointed to by DynamicResource or the dictionary with this resource at runtime.
I was going through some code in our product and saw some colleagues using ResourceDictionary.MergedDictionaries in a way I had not seen it used before:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<toolTips:ToolTips />
<styles:ControlStyles />
<icons:IconDictionary />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
tooltips:ToolTips and all the other elements in the MergedDictionaries are ResourceDictionaries.
The regular way of using these according to the internet is to use <ResourceDictionary Source="uri to your xaml file"/>.
So is there any practical difference between both?
If this way works why isn't it used more often as it plays well with code completion?
I've used ResourceDicionary this way only once on a big project and it was benefical in my situation.
Suppose that you have ResourceDictionary in MyDictionary.xaml file.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="YourNamespace.MyDictionary">
</ResourceDictionary>
You can add an x:Class attribute to the ResourceDictionary element and specify the fully qualified name of the code-behind class.
Let's create MyDictionary.xaml.cs with class MyDictionary (name can be different from the name of the xaml file).
public partial class MyDictionary
{
public MyDictionary()
{
InitializeComponent();
}
}
A class must be a partial class. The constructor must be added to the class and InitializeComponent method must be called. The InitializeComponent method will be automatically generated for the class if you set the x:Class attribute in MyDictionary.xaml
Now you can reference MyDictionary in MergedDictionaries
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<local:MyDictionary/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
If you add some DataTemplate into MyDictionary.xaml you can create event handlers in code-behind (handlers will be automatically generated by VS)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="YourNamespace.MyDictionary">
<DataTemplate x:Key="MyTemplate">
<Button Click="Button_Click"/>
</DataTemplate>
</ResourceDictionary>
Code-behind:
public partial class MyDictionary
{
public MyDictionary()
{
InitializeComponent();
}
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
// custom logic
// edit another element, etc.
}
}
If the class is inherited from the ResourceDictionary class then other resources can be accessed from the code-behind.
Example of usage of data template defined in MyDictonary:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<local:MyDictionary/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ContentControl ContentTemplate="{StaticResource MyTemplate}"/>
</Grid>
From my point of view the biggest advantages are that you can encapsulate logic into separated files (it's easy to maintain and add new features in big projects) and avoid referencing ResourceDictionaries by <ResourceDictionary Source="uri to your xaml file"/>.
I've came across this error, which I couldn't find the solution for. I'm implementing an mvvm application and in main window I'm setting the main DataContext in xaml using a loader:
in App.xaml:
<Application.Resources>
<viewModel:KinectViewModelLoader x:Key="KinectViewModelLoader"/>
</Application.Resources>
In MainWindow.xaml:
<Window x:Class="KinectFittingRoom.MainWindow"
...
DataContext="{Binding KinectViewModel, Source={StaticResource KinectViewModelLoader}}">
...
</Window>
Everything was running well, but now I wanted to add some dynamic resources, so I've created some xaml files containing styles and other elements.
In example:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ModelUIElement3D x:Key="BirthdayHatModel">
...
</ModelUIElement3D>
</ResourceDictionary >
To use them in MainWindow.xaml I've added them to App.xaml file as ResourceDirectory and then my application began to crash.
App.xaml:
<Application x:Class="KinectFittingRoom.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModel="clr-namespace:KinectFittingRoom.ViewModel"
StartupUri="MainWindow.xaml">
<Application.Resources>
<viewModel:KinectViewModelLoader x:Key="KinectViewModelLoader"/>
<ResourceDictionary x:Key="ResourceDictionary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/GlassButton.xaml"/>
<ResourceDictionary Source="Resources/Models/BirthdayHat.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
And now I'm getting an error on App.xaml.cs file saying that KinectFittingRoom.App.OnExit(System.Windows.ExitEventArgs) has no suitable method to override.
My overriden method:
protected override void OnExit(ExitEventArgs e)
{
KinectViewModelLoader.Cleanup();
base.OnExit(e);
}
Mabe someone could explain to me why adding ResourceDirectory node causes my application to throw an error? What can I do to include those resources and avoid such problem? I would appreciate any advice.
I think you need to change two things in your XAML:
In your App.xaml file Move the declaration of your ViewModel inside ResourceDictionary section. Also if possible you should delete x:Key="ResourceDictionary". So now your App.xaml should look like:
<Application x:Class..................>
<Application.Resources>
<ResourceDictionary>
<viewModel:KinectViewModelLoader x:Key="KinectViewModelLoader"/>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/GlassButton.xaml"/>
<ResourceDictionary Source="Resources/Models/BirthdayHat.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
If after following the above step your program does not work then please follow this step along. Change the DataContext Property of your window like the code shown below:
<Window x:Class="KinectFittingRoom.MainWindow"
DataContext="{StaticResource KinectViewModelLoader}">
...
</Window>
If still your application does not work then change the order of the lines in App.OnExit() as follows:
protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
KinectViewModelLoader.Cleanup();
}
I have a Windows Phone 8.1 solution that has a Standard Application Project and a Class Library Project. The idea is that I can, somehow, StaticResources down do the ClassLibrary so it can override the existing ones. I'll give you an example:
In my ClassLibrary I have a ClassLibraryDictionary.xaml with the following code:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ClassLibraryTest">
<SolidColorBrush x:Key="MyButtonColor" Color="#FF0000FF" />
</ResourceDictionary>
And the idea is that in my MainApplication I could have a Dictionary.xaml with the same StaticResource Key, and pass it to my ClassLibrary so it can override the default property, something like:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MainApplicationTest">
<SolidColorBrush x:Key="MyButtonColor" Color="#00FF00FF" />
</ResourceDictionary>
And passing it in code:
var mainAppDictionary = new ResourceDictionary();
mainAppDictionary.Source = new Uri("/using:MainApplicationTest;component/MainApplicationDictionary.xaml", UriKind.RelativeOrAbsolute);
classLibraryTest.SetResourceDictionary(mainAppDictionary);
The problem here is that I can't seem to use the ResourceDictionary instance in my ClassLibrary, and I'm not even sure this is the best way to do this.
So, how could I solve this?
I found out how to this and it is actually simple. The path I was using was not the correct one, so to sum it all up, the solution in XAML, if you were to do it in the App.xaml (in the MainApp) looks like this:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ms-appx://Common/yourclasslibraryname/ClassLibraryDictionary.xaml"></ResourceDictionary>
<ResourceDictionary Source="/Dictionary1.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
If you want to set it in code directly in the ClassLibrary you can do something like this:
In the MainApp.xaml.cs
myClassLibrary.MergeAllDictionaries(App.Current.Resources);
And in the ClassLibrary:
public void MergeAllDictionaries(ResourceDictionary appDictionary) {
// First copy all keys from MainApp to a new Dictionary
ResourceDictionary mainDictionary = new ResourceDictionary();
foreach(var keys in appDictionary.MergedDictionaries) {
foreach(var keys1 in keys) {
mainDictionary.Add(keys1.Key, keys1.Value);
}
}
// Then clear all
appDictionary.Clear();
// Get the ClassLibrary dictionary
ResourceDictionary classLibraryDictionary = new ResourceDictionary();
classLibraryDictionary.Source = new Uri("ms-appx://Common/yourclasslibraryname/ClassLibraryDictionary.xaml", UriKind.RelativeOrAbsolute);
// First add the ClassLibrary keys and values
appDictionary.MergedDictionaries.Add(classLibraryDictionary);
// Then add the old values, so that they overwrite the ClassLibrary ones
appDictionary.MergedDictionaries.Add(mainDictionary);
}
In my WPF application, user can select a command by doing a right click. Now, I have created a button and want to associate this method to the button.
What I have done so far:
In the XAML file I have:
<Button Content="Run Compare" Command="{x:Static RunCompare_Exectued}"></Button>
Then in ResourceDirectory section I am trying to give a reference to my file holding the method as
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myMethods="**Nothing Comes up here!!!**"
>
Usually I would hold Ctrl and hit the space bar but nothing shows up then I tried to type clr-namespace:FileNameConatiningMethod ... yet I'm getting error as:
Undefined CLR namespace. The 'clr-namespace' URI refers to a namespace 'Application.Commands' that is not included in the assembly.
Any help will be appreciated.
Thanks.
EDIT:
I have access to one of the files which has method A and B, however, I don't have access to method C and D in a different source file. Shouldn't this be OK by adding Namespace in the root tag of the XAML file?
let's say my namespace is ABC so I have:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:ABC">
Please check your approach against this one I found on MSDN.
Please also check that your code is compiling and there are no assembly reference conflicts.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<!-- String resource that can be localized -->
<system:String x:Key="localizedMessage">en-US Message</system:String>
</ResourceDictionary>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="StringResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>