Injecting Views into MainWindow - c#

I have the following problem:
I want to implement MvvM in Best-Practice style so I wanted to implement MvvM like in this Microsoft-Video. The video takes ~ 1 hour, so I compress the content:
In the App.xaml.cs the OnStartup-Event is being overwritten, so that I manually instantiate the MainWindow.
There's a MainViewModel which contains an ObservableCollection<ViewModelBase> property, the MainWindow's ItemsControl is bound to that
This MainViewModel is being instantiated in the App.xaml.cs and the MainWindow's DataContextis set to this.
The MainWindow.xaml contains a DataTemplate which is of type ViewModelBase and contains a MainView
So, I have several Views and ViewModels. But when I place several Views into the MainView, only one View has filled values (every time the View, which is being placed first in the MainView.xaml). I know how it should work:
The Views are all placed in the MainView and that MainView is shown in the MainWindow. Because I set the MainWindow's DataContext to the MainViewModel, the MainWindow's ItemsControl (it's ItemsSource) is successfully bound to the ViewModels collection of the MainViewModel.
But I did never set the DataContext of the particular Views to their corresponding ViewModel. Does Visual Studio automatically bind the corresponding Views and ViewModels due to naming convention?
However, only the View, which is being placed at first in the MainView, has beed filled with values. When I swap the 2nd and the 1. Views places in the XAML-File, the formerly 2nd View works now, but the formerly 1. View doesn't have any values filled in anymore. Why is that so?
Of Course i can add specific code, if you want.
But I did never set the DataContext of the particular Views to their corresponding ViewModel. Does Visual Studio automatically bind the corresponding Views and ViewModels due to naming convention?
Now I know, that the DataTemplate I set replaces each Instance of DataType with an instance of a class I want to be instantiated instead.
So each View will be mapped into the MainView (and then the MainView will be mapped into the MainWindow) by replacing each of the corresponding 'ViewModel'-instance with it's View.
One problem solved, and another one pops up:
I have a few styles declared in my App.xaml in a ResourceDictionary:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Orange.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
And when I add the DataTemplates I need:
<Application.Resources>
<DataTemplate DataType="{x:Type vm:OperationViewModel}" x:Key="OpKey">
<v:OperationView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:PlayerViewModel}" x:Key="PKey">
<v:PlayerView/>
</DataTemplate>
<ResourceDictionary x:Key="MetroStyle">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Orange.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
But then I get kind of a Black-Screen so that the declared style (not the DataTemplate) is not being applied. I really dont have much knowledge about ResourceDictionarys and the App.Xaml, so how can I solve this?

Related

Different ways of using ResourceDictionary.MergedDictionaries

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"/>.

UWP - Reference StaticResource from different style resource dictionary: Failed to assign to property 'Windows.UI.Xaml.ResourceDictionary.Source'

Hello my team and I recently started developing an win10 uwp application. Application will have a lot of views and components so heavy use of styles is expected, so we need to organize our styles through file/folder structure we did this using following structure (unfortunately I cannot embed images yet see the link):
Anyways my Resource.xaml merges all other dictionaries as following:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/Colors.xaml" />
<ResourceDictionary Source="/Resources/Icons.xaml" />
<ResourceDictionary Source="/Resources/Fonts.xaml" />
<ResourceDictionary Source="/Resources/Converters.xaml" />
<ResourceDictionary Source="/Resources/Buttons.xaml" />
<ResourceDictionary Source="/Resources/RadioButton.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
And in my App.xaml I reference this dictionary:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Resources.xaml" />
</ResourceDictionary.MergedDictionaries>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
</ResourceDictionary>
</Application.Resources>
Now I managed to find the source of the problem in my RadioButton.xaml I reference a brush defined in Colors.xaml using StaticResource lookup:
<Setter Property="Foreground" Value="{StaticResource TopMenuTextBrush}" />
If I remove this line everything will start but with it I get following exception:
Exception {Windows.UI.Xaml.Markup.XamlParseException: The text associated with this error code could not be found.
Failed to assign to property
'Windows.UI.Xaml.ResourceDictionary.Source' because the type
'Windows.Foundation.String' cannot be assigned to the type
'Windows.Foundation.Uri'. [Line: 28 Position: 37]} System.Exception
{Windows.UI.Xaml.Markup.XamlParseException}
Interesting thing is when I start the app with this line commented and uncomment it visual studio will recognize the brush and apply it correctly, it only breaks on application start.
We used same approach before when developing WPF, so I'm thinking it might have to do with something regarding application deployment.
All help is greatly appreciated.
Exception = {Windows.UI.Xaml.Markup.XamlParseException: The text associated with this error code could not be found.
The problem is that you have used wrong ResourceDictionary source . I found the Resources.xaml and other xaml file stored in the same level directory in your screenshot. So you could not declare the parent directory of these xaml files within source. Please modify ResourceDictionary like the following
<ResourceDictionary Source="Colors.xaml"/>
For more you could refer to ResourceDictionary and XAML resource references.

Fluent ribbonTabItem not visible in designer?

i am Using the Fluent-Ribbons to create my view in wpf.
to have a better organisation of my code i wanted to put the different RibbonTabItems into their own files.
The problem is:
the designer does not show the content of the ribbontab.
I only see the a blank page.
Is there a way to make the RibbonTab visible in the designer?
If anyone else lands here from google, I was having this situation where the ribbon was not only invisible in the designer, but also not showing at runtime. After spending some time, I found that you have import generic fluent ribbon theme resources into your Window or Application Resources section, like this:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Fluent;component/Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
After this my ribbon started showing in the designer as well as at runtime.
You can also use other themes in the same way. Just override the generic theme like this:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Fluent;component/Themes/Generic.xaml" />
<!-- change "Cobalt" to the color you want -->
<ResourceDictionary Source="pack://application:,,,/Fluent;component/Themes/Themes/Dark.Cobalt.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
Hope this helps someone down the road.
Credit to the project documentation at github.

WPF's application wide styles in Windows Forms context

We migrate from WinForms to WPF... slowly =)
No we use WPF User Controls with ElementHost.
Is it possible to define application wide resources in this context? In pure WPF Application.Resources stands for it. But there's no WPF App when integrating with WinForms.
You can use a WPF application object even if your project is a WinForms one with a few separate WPF forms or controls. The object won't be precreated for you, but if you manually create it, simply by new App() (or even without a derived class, new System.Windows.Application()), everything in your project will see it.
You can create a common ResourceDictionary and add it to the Resources of your UserControls. That way you just have to change your Styles in one location.
Dictionary1.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</ResourceDictionary>
and add it to your UserControl using MergedDictionarys
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
or just add it to the Control's Resources like this
<UserControl.Resources>
<ResourceDictionary Source="Dictionary1.xaml"/>
</UserControl.Resources>

In WPF how do I reference a static resource that is defined in a different XAML file?

In WPF how do I reference a static resource that is defined in a different XAML file? It's in the same project.
The other XAML file will need to be a resource dictionary. You merge it into the current file using the MergedDictionaries property of the current ResourceDictionary. See Merged Resource Dictionaries on MSDN. Their example:
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="myresourcedictionary.xaml"/>
<ResourceDictionary Source="myresourcedictionary2.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
Then within that Page object you can reference static resources defined in myresourcedictionary.xaml or in myresourcedictionary2.xaml.
"different XAML file" could mean a few different things:
App.xaml: Resources are automatically included in the resource tree of anything that's opened so you don't need to do anything extra.
Window or Page .xaml: Resources can be accessed by any child of an instance of the object like a UserControl that is used in a Window.
ResourceDictionary: Needs to be explicitly merged into the resource tree somewhere above where it is used. This can be App.xaml, Windowxx.xaml, or some lower level element. Use ResourceDictionary.MergedDictionaries to do this.
There are also lots of alternate ways to specify the path but this is the simplest:
<Window>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/MyResourceDict.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>

Categories