XAML Inheritance (not code-behind) - c#

How is inheritance accomplished in XAML?
Is it true that only the code-behind can be inherited and not the .xaml (related question)? Is including the parent in the child control's namespace the only way of doing it?
There seems to be no general "inheritance" per se in XAML. There are questions about inheriting UserControl, etc. but not general inheritance.
Problem:
I have 2 xaml files, File1.xaml and File2.xaml, which are very alike. Can I create a SuperFile.xaml and put the bulk of the following code in it?
<UserControl ... >
<Grid>
<Grid.RowDefinitions ... />
<DockPanel ... >
<ToolBar ... >
<!-- Some Buttons here:
File1.xaml to contain the Buttons "View" and "Export"
File2.xaml to contain the Buttons "Edit" and "Delete"
-->
</ToolBar>
</DockPanel>
<igDP:XamDataGrid MouseDoubleClick="xamDataGrid1_MouseDoubleClick" ... />
</Grid>
</UserControl>
The only things that differ in File1.xaml and File2.xaml are:
Buttons in the ToolBar (see comment in the code)
The properties of XamDataGrid, primarily the events (what they do in each case).
How can I achieve this? Would I have to write the code-behind files for both the children separately?

You can use a ResourceDictionary
Put all your generic templates and styles in a ResourceDictionary, then have both your UserControls import that ResourceDictionary
<UserControl.Resources>
<ResourceDictionary Source="BaseStylesAndTemplates.xaml" />
</UserControl.Resources>

Related

How to set WinFormHost object dynamically?

I am wrapping Windows Form legacy control inside WPF control , I am doing this for a few Windows Form controls. ie:
// WinFormHost control, only AWrapper is shown here, but there
//are BWrapper, CWrapper etc
public class AWrapper : WindowsFormsHost
{
Child=new ALegacyWinFormControl();
}
//WPF control, similarly there are BControl, CControl etc
<UserControl x:Class="AControl">
<local:AWrapper />
</UserControl>
At my ResourceDictionary I am defining a key for each WPF controls
// each WPF control has a key
<ResourceDictionary>
<DataTemplate x:Key="AControlKey">
<AControl />
</DataTemplate>
<DataTemplate x:Key="BControlKey">
<BControl />
</DataTemplate>
</ResourceDictionary>
There is one layer of duplication that I want to eliminate-- I will have to define each WPF control for each WindowsFormsHost wrapper, which is redundant. Is there anyway that I can do away with the UserControl object, and connect the DataTemplate straight with the WindowsFormsHost control? ie: I am looking at something like this:
// This wouldn't work
<ResourceDictionary>
<DataTemplate x:Key="AControlKey">
<AWrapper/>
</DataTemplate>
<DataTemplate x:Key="BControlKey">
<BWrapper/>
</DataTemplate>
</ResourceDictionary>
But the above doesn't seem to work. Anyway to make the above work? Is it possible at all?
Edit:
This should work provided that AWrapper is a WindowsFormsHost:
<DataTemplate x:Key="AControlKey">
<local:AWrapper/>
</DataTemplate>
Sample usage:
<ContentControl Content="." ContentTemplate="{StaticResource AControlKey}" />
No UserControl is involved.
local maps to the namespace in which the AWrapper class is defined:
xmlns:local="clr-namespace:WpfApplication1"

Import view from resource file

I have a resources file Grids.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Label x:Key="SomeTestLabel">Hello There</Label>
<Grid x:Key="HomeGrid">
<Label Content="{StaticResource SomeTestLabel}"></Label>
</Grid>
</ResourceDictionary>
And in my Menus.xaml file I have
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TabItem x:Key="HomeTab" Header="Home">
<Grid><!-- PROBLEM IS RIGHT HERE --></Grid>
</TabItem>
</ResourceDictionary>
Is it possible to link <Grid><!-- PROBLEM IS RIGHT HERE --></Grid> with <Grid x:Key="HomeGrid">...</Grid>?
Is there a better View I could use?
Is there a better way to do this?
The main reason I'm doing this is to refactor code out of one file (MainWindow.xaml) and into various other files, so that the main file and main resources file don't get cluttered with random pieces of code
A <ResourceDictionary /> is not ment to be a central place to declare controls. Things that are declared in one of those dictionaries is ment to be used by controls (e.g. styles, brushes, themes, common images, converters and templates).
However, control declarations (e.g. a <Grid />) is always an instance of that particular class that will be rendered by the WPF framework. A control can only exist at one place at a time, therefore, placing one inside a ResourceDictionary is not a good idea (it's not reusable anyway). Control declarations always belong inside the UserControl, Window or other hosting control where you want it to be displayed.

Catel framework - replace view

I'm building application with multiple modules. Each of module contains a viewmodel and view.
I would like to create solution, for automatically show SelectedModule in a part of my application.
Assume that I have MainWindow view like this:
<catel:UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:catel="http://catel.codeplex.com" xmlns:dxsch="http://schemas.devexpress.com/winfx/2008/xaml/scheduler"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
x:Class="OrchestraCatel.Views.MainWindow">
<DockPanel LastChildFill="True">
<ContentControl x:Name="Ribbon" DockPanel.Dock="Top">
<!-- My Ribbon-->
</ContentControl>
<ContentControl x:Name="MainView" DockPanel.Dock="Top">
<!-- My Main Page-->
</ContentControl>
</DockPanel>
</catel:UserControl>
And I would like to show a UserControl specified in another DLL inside MainView ContentControl after Ribbon item click.
Both, Ribbon Button and MainView view are in module DLL
I had an idea to include SelectedViewModel inside my MainPage ViewModel, and then, create DataTemplates for each ViewModel, but this solution will break my vision of Modules, which should be independent.
Is there a way in Catel to replace a view with another one? From anywhere?
I think Prism solves this issue for you. Please take a look at the integration of Prism with Catel:
https://catelproject.atlassian.net/wiki/display/CTL/Catel.Extensions.Prism

What to do with EventHandlers in a ControlTemplate defined in a ResourceDictionary?

This question is more about neat programming along the MVVM lines rather than a 'how-do-I-get-this-to-work' one.
I wanted to keep all the ControlTemplates for my DataTemplates in a separate ResourceDictionary file, for clarity. So, in the main Window it looks like this, e.g:
<DataTemplate DataType="{x:Type localm:MusicSystem}">
<Control Template="{StaticResource MusicSystemTemplate}"/>
</DataTemplate>
However, the ControlTemplate for this very Class contains a ListBox which is supposed to react to certain events - have some handlers, as here:
<ControlTemplate x:Key="MusicSystemTemplate">
<StackPanel ... >
<ListBox x:Name="SystemListBox" ...
PreviewMouseMove="SystemListBox_PreviewMouseMove"
PreviewMouseDown="SystemListBox_PreviewMouseDown"
MouseEnter="SystemListBox_MouseEnter"
MouseLeave="SystemListBox_MouseLeave">
<!-- More ListBox stuff here -->
</ListBox>
<!-- More other stuff here -->
</StackPanel>
</ControlTemplate>
For now I'm keeping this template in the XAML of the main Window, and the handlers in its code behind, but that's not what I want. If it was a Button, I'd create a command and bind it one way or the other. But since it's a ListBox, I'm unfortunately deprived of that possibility. I wouldn't like to resort to the code behind of the ResourceDictionary, because this is not what they are for. Is there a neat and not overly verbose way around it? Or maybe there is something wrong with declaring handlers within a Template altogether?
You can use attached behaviors for this. They can either be behaviors attached using Blend's Interactivity assembly, or just attached properties which add and remove event handlers when their values are changed.
Overview: Behaviors in WPF introduction.

Resources for WPF designer

I have the following structure of objects in my WPF application (simplified):
Main window
<Window>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedResources>
<ResourceDictionary Source="Styles.xaml" />
</ResourceDictionary.MergedResources>
</ResourceDictionary>
</Window.Resources>
<ContentControl>
<ContentControl.Resources>
<DataTemplate DataType="{x:Type local:MyViewModel}">
<local:MyEditor />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
...
Then, the editor:
<UserControl>
<!-- No resources here - getting styles from parent -->
...
</UserControl>
Resources in the main window are being managed dynamically (in certain circumstances I clear them and load another set to match theme of application), so I cannot embed the styles in UserControl (otherwise I would have to load styles in that UserControl dynamically as well). Of course apart from fact, that I actually don't even have to embed these styles in user control, because it will get them from parent.
But.
If I don't specify link to resources in XAML, the designer looks very sad (despite complicated structure of the UserControl):
Is there a way to provide information about related resources for the designer only?

Categories

Resources