WPF Global Resources in App.xaml - wpf

I have created a custom Treeview control and am trying to access the HierarchicalDataTemplate resource of this control from another page in the same project.
my this.sceneTemplate property is coming up null. I have looped through all the objects in the dictionary and it does exist.
How can I access this template?
Thanks
App.xaml
<Application x:Class="Foo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
DispatcherUnhandledException="App_DispatcherUnhandledException">
<Application.Resources>
<ResourceDictionary>
<!--Merge the global resource to the application-->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Global.xaml"/>
<ResourceDictionary Source="Resources/Scrollbar.xaml"/>
<ResourceDictionary Source="/Controls/TreeView/Themes/Generic.xaml"/>
<ResourceDictionary Source="/Controls/ListButton/Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Where I am trying to access the resource from my Scene.xaml.cs page
public LeagueDataTemplateSelector()
{
if (Application.Current != null)
{
this.sceneTemplate = (HierarchicalDataTemplate)Application.Current.FindResource("Scene");
this.ItemTemplate = (HierarchicalDataTemplate)Application.Current.FindResource("Procedure");
this.sub1Template = (HierarchicalDataTemplate)Application.Current.FindResource("SubProc1");
this.sub2Template = (HierarchicalDataTemplate)Application.Current.FindResource("SubProc2");
}
}
Scene HierarchicalDataTemplate
<HierarchicalDataTemplate x:Key="Scene" ItemsSource="{Binding XPath=Level}"
ItemContainerStyle="{StaticResource RadTreeViewItemStyleSub1}"
ItemTemplate="{StaticResource Procedure}"
>
<Border>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label VerticalContentAlignment="Center"
BorderThickness="0"
BorderBrush="Transparent"
Foreground="{StaticResource ListItemUnHighlight}"
FontSize="24"
Tag="{Binding XPath=#name}"
MinHeight="55"
Cursor="Hand"
FontFamily="Arial"
KeyboardNavigation.TabNavigation="None"
Name="SubItem" >
<Label.ContextMenu>
<ContextMenu Name="editMenu">
<MenuItem Header="Edit"/>
</ContextMenu>
</Label.ContextMenu>
<TextBlock Text="{Binding XPath=#name}" VerticalAlignment="Center" TextWrapping="Wrap"></TextBlock>
</Label>
</Grid>
</Border>
</HierarchicalDataTemplate>
Update - Answer
Our program has a breadcrumb control that works by using a list of pages to navigate through. This list of pages was getting added during the splash screen before InitializeComponent was being ran. I moved this up above the page list code and everything in App.xaml is now found.

Our program has a breadcrumb control that works by using a list of pages to navigate through. This list of pages was getting added during the splash screen before InitializeComponent was being ran. I moved this up above the page list code and everything in App.xaml is now found.

Related

Set value in xaml using class field

I have a DataGrid as:
<DataGrid Grid.Row="4" Name="grvAllCry" Margin="5,5,5,5" ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Rank" Width="10*" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Rank}" Foreground="#46BF6E"></Label>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
As you can see, I set Foreground of row of DataGrid is "#46BF6E". But I have many DataGrid and I want to re-use this variables. Something like:
public static class Config
{
public static string MyGreen = "#46BF6E";
public static string MyRed = "#D14836";
public static string MyBlue = "#428BCA";
}
Is there a way I can create a class like that and use it's variable in many different xaml files? For examples:
<Label Content="{Binding Rank}" Foreground="MyGreen"></Label>
I dont know how to call variable from .cs file while in xaml file, pls help me.
You could create a new ResourceDictionary where you define a Brush resource:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="myBrush" Color="#46BF6E"/>
</ResourceDictionary>
If you want to be able to reference this resource throughout your entire application, you can then merge this resource dictionary into your App.xaml:
<Application x:Class="WpfApp1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
...and reference the resource from any view using the StaticResource markup extension:
<Label Content="{Binding Rank}" Foreground="{StaticResource myBrush}"></Label>
it is possible to referense static property or field (including const fields) using {x:Static ...} extension. For Config class it should be:
<Label Content="{Binding Rank}" Foreground="{x:Static myNameSpace:Config.MyGreen}"/>
xaml file should include namespace definition of Config class (xmlsns:myNameSpace="....")
However, reusable elements are usually defined as Resources. Resources which are visible across the application are defined in App.xaml:
<Application.Resources>
<SolidColorBrush x:Key="MyGreen" Color="#46BF6E"/>
<SolidColorBrush x:Key="MyRed" Color="#D14836"/>
<SolidColorBrush x:Key="MyBlue" Color="#428BCA"/>
</Application.Resources>
such resources can be used from StaticResource/DynamicResource extension:
<Label Content="{Binding Rank}" Foreground="{StaticResource MyGreen}"/>

How to use static resources for automatic DataTemplate resolution in ListView

I have
<ListView ItemsSource="{Binding Path=Fruit}">
<ListView.Resources>
<DataTemplate DataType="Apple">
<TextBlock Text="This is an apple"/>
</DataTemplate>
<DataTemplate DataType="Orange">
<TextBlock Text="This is an orange"/>
</DataTemplate>
<DataTemplate DataType="Potato">
<TextBlock Text="Lets assume potato is a fruit"/>
</DataTemplate>
</ListView.Resources>
where Fruit is
ObservableCollection<IFruit> Fruit = new Observable Collection<IFruit>();
public class Apple:IFruit{ }
public class Orange:IFruit{ }
public class Potato:IFruit{ }
This works fine. But since all of the seperate Fruit markups are quite large, I'd rather move their DataTemplates to their own ResourceDictionaryies in seperate files.
What I am trying to do is
<ListView ItemsSource="{Binding Path=Fruit}">
<ListView.Resources>
<StaticResource ResourceKey="AppleDataTemplate" />
<StaticResource ResourceKey="OrangeDataTemplate" />
<StaticResource ResourceKey="PotatoDataTemplate" />
</ListView.Resources>
where DataTemplates are
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:models="clr-namespace:MyApp.Models">
<DataTemplate x:Key="AppleDataTemplate" DataType="Apple">
<TextBlock Text="This is an apple"/>
</DataTemplate>
</ResourceDictionary>
but this throws
{"'XAML Node Stream: Value of 'System.Windows.Markup.StaticResourceHolder' must follow a StartObject and StartMember.' Line number '130' and line position '18'."}
Where Line number '130' is the <StaticResource> element.
My question then is how does one use static resources for automatic DataTemplate resolution in a ListView?
According to MSDN, shouldn't the StartObject and StartMember be implicit for those elements? Similar to how <Party.Favors> is defined in the documentation?
You could merge those DataTemplate ResourceDictionarys into ListView.Resources by doing:
<ListView ItemsSource="{Binding Path=Fruit}">
<ListView.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="AppleTemplate.xaml" />
<ResourceDictionary Source="OrangeTemplate.xaml" />
<ResourceDictionary Source="PotatoTemplate.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ListView.Resources>
</ListView>
Then, the DataTemplates will be available to ListView. Alternatively, you can merge these ResourceDictionarys at a higher level (i.e. the UserControl XAML file where you have your ListView defined).
You may want to remove x:Key from your DataTemplate definitions in ResourceDictionarys.

Using one class library (and theme) as basis to another class library

Still learning this stuff on WPF, themes, derivations, etc.
I understand basics on the "Themes\Generic.xaml", and then setting your application's app.xaml file to include the resource dictionary pointing to the theme in question.
So, thats fine from an application project perspective. Now, how about from a class library/dll file. I have a DLL project which I want to use as the basis of all controls in my project. In that, I have the Themes/Generic.xaml and have it coded up with some basics to confirm visual design implementation (originally confirmed ok, when tested under an App/exe project).
Now, I want this theme at a level BEFORE the actual application. Again, this is the baseline. Now, I add a second library of custom grouped controls (for example, a user control for address information... multiple address lines, city, state, zip, labels, etc). I want this second library to reference the first library with the themes, so I can see visually at design time what it will look like (alignments, colors, fonts, etc).
What / where should I be looking to let one DLL know about the merge dictionaries that are the basis in the first DLL. Hope this makes sense.
-- EDIT -- for clarification
First Class Library... "MyThemeLibrary" compiles into a .dll
In this dll is path/file of "/Themes/MyTheme.xaml"
As suggested by first answer, if I have a Resource Dictionary in the first library, I can reference it in anything else that I will derive from it. So, I have
<ResourceDictionary x:Name="MyGenericTheme"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Themes/MyTheme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Second Class Library... "SecondLevel" compiles into a .dll
In this, I have a user control that I want to put a grid for columns/rows, labels and textbox controls into. I want the controls to respect the colors, fonts, sizes, alignments as defined in the "MyTheme.xaml" of the first dll.
<UserControl x:Class="SecondLevel.multipleControlContainer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Label Content="Something"
Grid.Row="0" Grid.Column="0" />
<TextBox Text="Testing" Grid.Row="1" Grid.Column="1" />
</Grid>
</UserControl>
So, how / what should I do the necessary reference, declaration, inclusion of resource dictionary from the first library into the second.
make a reference to your dll and if you know where your theme is located you can do this one
<Application x:Class="My.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Common base theme -->
<ResourceDictionary Source="pack://application:,,,/Your.Base.Dll;component/YourResDictionary/YourTheme.xaml" />
<!-- here comes your custom theme -->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
do this in the App.xaml
EDIT after clarification (look at the comments)
<UserControl x:Class="SecondLevel.multipleControlContainer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Common base theme -->
<ResourceDictionary Source="pack://application:,,,/Your.Base.Dll;component/YourResDictionaryFolder/MyGenericTheme.xaml" />
<!-- Custom theme -->
<ResourceDictionary Source="pack://application:,,,/Another.Dll;component/AnotherResDictionaryFolder/MyCustomTheme.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<!-- all controls in this usercontrol respect the styles in MyGenericTheme.xaml"
if you use implicite styles-->
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Label Content="Something"
Grid.Row="0"
Grid.Column="0" />
<TextBox Text="Testing"
Grid.Row="1"
Grid.Column="1" />
<!-- if you use explicit styles then you must do this -->
<TextBox Style="{StaticResource myTextBoxStyle}"
Text="Testing"
Grid.Row="1"
Grid.Column="1" />
</Grid>
</UserControl>

Content of ContentControl in Resource

I have a ContentControl in a RadTileView. If I put in some hard coded text into the content property it works fine. (code below)
<ContentControl Grid.Row="2" Grid.Column="0" Content="Hello World"></ContentControl>
That works...if I put the content into the UserControl.Resources section my application freezes up and displays nothing.
<ContentControl Grid.Row="2" Grid.Column="0" Content="{StaticResource TabControlContent}"></ContentControl>
<UserControl.Resources>
<TextBlock x:Key="TabControlContent" Text="hello world"></TextBlock>
</UserControl.Resources>
Ultimately I would like to have the context be a RadTabControl..but for now Id settle on just having that textblock render.
To get a string into your ContentControl you would, add
xmlns:sys="clr-namespace:System;assembly=mscorlib"
to your usings. Then add this
<UserControl.Resources>
<sys:String x:Key="SingleString">Hello World</sys:String>
</UserControl.Resources>
Which would allow
<ContentControl Content="{Binding Source={StaticResource SingleString}}"/>
Hope this helps.

How can I create a DataTemplate for a collection?

I would like to be able to create a DataTemplate to be used when a collection is passed into a control.
I am building a single control, that when passed an object, or a collection of objects, the view of the user control conforms to the template defined for the object type.
For example, this is a user control I have, that switches views when an object is passed into the .Content property.
<UserControl x:Class="Russound.Windows.UI.UserControls.MAX.OMS_Main_Screen.OMSContextSwitcher"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Entities="clr-namespace:Russound.Components.ReturnAuthorization.Entities;assembly=Russound.Components"
xmlns:Return_Authorization="clr-namespace:Russound.Windows.UI.UserControls.Return_Authorization"
xmlns:CallLog="clr-namespace:Russound.Windows.UI.UserControls.CallLog"
xmlns:Entities1="clr-namespace:Russound.Components.Membership.Entities;assembly=Russound.Components"
xmlns:Membership="clr-namespace:Russound.Windows.UI.UserControls.Membership"
xmlns:Entities2="clr-namespace:Russound.Components.Commerce.MAX.Entities;assembly=Russound.Components"
xmlns:OMS_Main_Screen="clr-namespace:Russound.Windows.UI.UserControls.MAX.OMS_Main_Screen"
xmlns:Entities3="clr-namespace:Russound.Components.CallLog.Entities;assembly=Russound.Components"
MinHeight="600" MinWidth="700">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Russound.Windows;component/UI/RussoundDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
<DataTemplate DataType="{x:Type Entities3:Case}" >
<CallLog:CaseReadOnlyDisplay DataContext="{Binding}" />
</DataTemplate>
<DataTemplate DataType="{x:Type Entities:RAMaster}">
<Return_Authorization:RaMasterUi DataContext="{Binding}" />
</DataTemplate>
<DataTemplate DataType="{x:Type Entities1:RussUser}">
<Membership:CMCControlWpf DataContext="{Binding}" />
</DataTemplate >
<DataTemplate DataType="{x:Type Entities2:MaxCustomer}">
<OMS_Main_Screen:MaxCustomerConfigWpf DataContext="{Binding}" />
</DataTemplate >
</ResourceDictionary>
</UserControl.Resources>
</UserControl>
I would like to be able to do something like:
<DataTemplate DataType="{x:Type IEnumerable<MaxCustomer>}">
<OMS_Main_Screen:MaxCustomerConfigWpf DataContext="{Binding}" />
</DataTemplate >
but I always get a compiler error, so I am at somewhat of a loss.
You can create a typed collection and use that type instead of the IEnumerable directly
public class MyCollection:IEnumerable<MaxCustomer>
{
....
}
<DataTemplate DataType="{x:Type Entities:MyCollection}">
<OMS_Main_Screen:MaxCustomerConfigWpf DataContext="{Binding}" />
</DataTemplate >

Resources