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"
I have problems with matching Ressource Dictionaries for a specific type in my project.
At start of my application my programm takes all .dll files in the folder and bind the .dlls to my project. After that I will search in all Assemblies for .xaml Files also the Ressource Dictionaries in my different dlls.
At the end I got a list with my Ressource Dictionaries.
Okay here is my problem now...How can I select the right dictionary for my type in the list View dynamicly. The second thing is how can I match the Dictionary Templates only to 1 control in my Window?
When the type of the items in my list view are changing check again for the right dictionary maybe i need another one
Here is an example of 1 dictionary
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PresentObjectDataTemplate">
<Style TargetType="ListView">
<!-- My Style for my ListView Control-->
</Style>
<!-- My Data Templates only for 1 Control-->
<DataTemplate DataType="{x:Type local:Entity1}">
<StackPanel>
<TextBox Text="{Binding A1}"/>
<TextBox Text="{Binding A2}"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Entity2}">
<StackPanel>
<TextBox Text="{Binding A1}"/>
<TextBox Text="{Binding A2}"/>
</StackPanel>
</DataTemplate>
My MainWindow has 3 Controls
A treeView to select my List
A listview to show the objects in the list
A contentcontrol to show the properties of a selected object
When I merge the dictionary to the window ressources my list view and my content control will use the datatemplates. But i want that the templates only used in the contentcontrol
Here a picture from my idea for better understanding
myPicture
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.
I am writing a style for a custom control derived directly from Control. Visual Studio places the style for a "Custom Control (WPF)" in the Themes\generic.xaml file. My style contains an image which I can't get displayed, seems there's something special about how to set the Source for an image from within the generic.xaml file.
I managed to reproduce the issue with a simpler scenario. Create a "WPF Custom Control library" then add a style for buttons like so, in the themes\generic.xaml . Here's my complete generic.xaml:
<ResourceDictionary
...
<Style TargetType="{x:Type Button}">
<Setter Property="Content">
<Setter.Value>
<Image Source="SmallHandle.png"></Image>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
After this I have create a UserControl (in the same project) containing just a button (for the sake of testing out the style) like so:
<UserControl x:Class="BlendControls.UserControl1"
...
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Button/>
</UserControl>
I have added the SmallHandle.png in the root project directory, in the themes directory, I have added it also to the good old Resources page, tried changing the build action to resource, embedded resource, tried copying the image manually to the build directory, but to no effect. The image is never displayed.
This must be related to the generic.xaml file, because copying the entire style to the same file where the Button is placed works fine. That is, the following works as expected:
<UserControl x:Class="BlendControls.UserControl1"
...
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Content">
<Setter.Value>
<Image Source="SmallHandle.png"></Image>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Button></Button>
</UserControl>
So, how should I set the Source of images from generic.xaml? Or alternatively, where should I put the styles/templates for custom controls?
---- Solution ----
As pointed out by Sheridan, I have to use the "full" pack URI notation as:
pack://application,,,/MyAssembly;components/SmallHandle.png
This looks strange to me, as the image is in the same assembly. Not sure, looks like I am referencing from outside the dll.
There's nothing unusual about accessing an image in Generic.xaml, you're just not referencing it correctly. You can reference a resource file in the project assembly using this format:
<Image Source="/AssemblyName;component/Subfolder/SmallHandle.png" />
If your images are directly inside the project root (which is not recommended), then you can access them like this:
<Image Source="/AssemblyName;component/SmallHandle.png" />
If your images are in a folder in another project, then you can access it like this:
<Image Source="/ReferencedAssembly;component/Subfolder/SmallHandle.png" />
See the Pack URIs in WPF page on MSDN for more information.
UPDATE >>>
In .NET 4, the above Image.Source values would work. However, Microsoft made some horrible changes in .NET 4.5 that broke many different things and so in .NET 4.5, you'd need to use the full pack path like this:
<Image Source="pack://application:,,,/AssemblyName;component/Images/image_to_use.png">
If you don't feel as though your generic.xaml is being picked up, you can reference it from your App.cs.xaml like this:
<App.Resources>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MY.NAMESPACE;component/Themes/generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</App.Resources>
Your generic.xaml file should be marked as "Resource".
Also, your image file should be marked as "Resource".
Finally, reference your ImageSource like this:
<Image Source="Themes/IMAGE.png" />
or try
<Image Source="../Themes/IMAGE.png" />
Personally, I like to put my style templates in their own .xaml file, and reference them all as MergedDictionaries.
Typed base style in Themes\Generic style is automatically applied only to Custom Control.
If you need use typed based style in your user control you need add generic.xaml to user control resources.
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Also change Image Source URI to
<Image Source="pack://application:,,,/WpfCustomControlLibrary1;component/SmallHandle.png" />
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>