WPF share resourcedictionaries among controls - wpf

I have 2 dictionaries merged in my WPF app (base dict merged with skin dict).
It works very fine on the MainWindow, but when I added a new WPF Window, it seems unable to access the StaticResource.
This is the code of the new Window:
<Window x:Class="Sc2ReplayMonkey.PleaseWaitWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:local="clr-namespace:Sc2ReplayMonkey"
Title="PleaseWaitWindow" Height="300" Width="300">
<Grid Style="{StaticResource WindowBackground}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Style="{StaticResource WindowTextelement}" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">
Please wait while the replays
</TextBlock>
<TextBlock Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
are parsed and serialized
</TextBlock>
</Grid>
</Window>
I get the error "Cannot find the resource named "WindowBackground".
It is defined in the skin dict as:
<Style x:Key="WindowBackground" TargetType="{x:Type Grid}">
<Setter Property="Background" Value="Black" />
</Style>
What did I miss?

I think you need to add
Resources.MergedDictionaries.Add(resources);
in you App.cs class once f.e in Initialize() method. Then your dictionary will be accessible from any windows.

This solved the problem, I simply added a line in PleaseWaitWindow's constructor: Resources = main.Resources; main being the MainWindow

Related

Wpf app with AvalonDock docking layout system

I am creating a small wpf program in .net5. It should have a tab system and a sidebar. The Dirkster.AvalonDock library github is suitable for my purposes. Installed version 4.60.0. I just started getting to know this library. The difficulty arose with the sidebar. LayoutAnchorablePane is responsible for its output. But the result is not what I expect.
I need to get something like this
img1
There is now
img2
View code:
<Window x:Class="TestApp.Views.MainWindowView"
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:vm="clr-namespace:TestApp.ViewModels"
xmlns:cm="http://www.caliburnproject.org"
mc:Ignorable="d"
Width="800" Height="450"
Title="MainWindow">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<DockingManager x:Name="DockManager" Grid.Column="0"
DocumentsSource="{Binding Items}"
AnchorablesSource="{Binding MenuItems}"
>
<DockingManager.LayoutItemTemplate>
<DataTemplate>
<ContentControl cm:View.Model="{Binding Content}" IsTabStop="False" />
</DataTemplate>
</DockingManager.LayoutItemTemplate>
<DockingManager.LayoutItemContainerStyle>
<Style TargetType="{x:Type LayoutItem}">
<Setter Property="Title" Value="{Binding Model.DisplayName, Mode=OneWay}"/>
<Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}"/>
</Style>
</DockingManager.LayoutItemContainerStyle>
<LayoutRoot>
<LayoutPanel>
<LayoutDocumentPaneGroup>
<LayoutDocumentPane />
</LayoutDocumentPaneGroup>
<LayoutAnchorablePaneGroup>
<LayoutAnchorablePane DockMinWidth="300" />
</LayoutAnchorablePaneGroup>
</LayoutPanel>
</LayoutRoot>
</DockingManager>
</Grid>
The viewmodel code is not important, I think. Also installed in the project is caliburn.micro
Please tell me how to get the sidebar as in the first picture.
You have to install VS2013 theme package (link) then use the light version like the following:
<DockingManager.Theme>
<Vs2013LightTheme />
</DockingManager.Theme>

access codebehind method from resource dictionary in WPF

I have following grid inside WPF XML file
<Grid Grid.RowSpan="2" >
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height = "Auto" />
</Grid.RowDefinitions >
<telerik:RadAutoCompleteBox TextSearchMode = "Contains" Grid.Column= "0" Grid.Row= "0" Name="cmbStyleNo" Margin= "5"
DisplayMemberPath="SAMPLE_ID" ItemsSource="{Binding Styles}"
SelectionMode= "Single" AutoCompleteMode= "Suggest" NoResultsContent= "No Matches" SelectionChanged= "val_SelectionChanged" />
</Grid >
above RadAutoCompleteBox SelectionChanged="val_SelectionChanged" code behind method exist in its code-behind file like follows
private void val_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
...
}
Then I have requirement populate above same grid in another window using resource dictionary. so I copied that grid to that ResourceDictionary like follows
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:samplePrjkt"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation">
<ToolBar x:Key="MyToolbar" Height="120">
<!--Template-->
<GroupBox Header="Template" Style="{StaticResource ToolbarGroup}" Margin="3">
<StackPanel Grid.Row="1" Orientation="Horizontal">
<StackPanel Orientation="Vertical" Margin="0,2,0,2">
<Grid Grid.RowSpan="2" >
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<telerik:RadAutoCompleteBox TextSearchMode="Contains" Grid.Column="0" Grid.Row="0" Name="cmbStyleNo" Margin="5"
DisplayMemberPath="SAMPLE_ID" ItemsSource="{Binding Styles}"
SelectionMode="Single" AutoCompleteMode="Suggest" NoResultsContent="No Matches" SelectionChanged="val_SelectionChanged"/>
</Grid>
</StackPanel>
</StackPanel>
</GroupBox>
</ToolBar>
</ResourceDictionary>
then once I compile this I'm getting following error
'ResourceDictionary' root element requires a x:Class attribute to
support event handlers in the XAML file. Either remove the event
handler for the SelectionChanged event, or add a x:Class attribute to
the root element.
You need to manually add a code-behind file for the ResourceDictionary and define the val_SelectionChanged event handler in this file.
Please refer to the following link for more information and an example of how to do this:
Is it possible to set code behind a resource dictionary in WPF for event handling?
You basically just create a new class and name it "Dictionary1.xaml.cs" where "Dictionary1" is the name of your resource dictionary XAML file and then you set the x:Class attribute in the XAML file:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication1.Dictionary1"
...

Datagrid with a column of buttons in wpf

I have a datagrid populated with some data. It looks something like this----
Security RegisterDate CUSIP ISC Source Employee
INVESCO 12/3/2007 G4921P105 818216804 Disk Ram
INVESCO 11/1/2011 G4921P106 818216805 Disk Shyam
Here, in the third column named CUSIP i actually wanted a column of buttons where the CONTENT property of the button is to be bound with the CUSIP property. So, for eg, first row 3rd column should display a button with "G4921P105" written over it. I was wondering if this could be done. Also, this button when clicked is supposed to open another window.
I am attatching the XAML code for this view.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Row="0" FontWeight="ExtraBold" FontSize="25" Content="{Binding CompanyCUSIPChangeData[0].Security}"></Label>
<Label Grid.Row="1" FontWeight="ExtraBold">Previous Registers</Label>
<DataGrid Grid.Row="2" ItemsSource="{Binding Path=CompanyCUSIPChangeData}" HorizontalAlignment="Left" CanUserAddRows="False">
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="FontWeight" Value="Bold" />
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>
</Grid>
I did a lot of research but still could not find much to solve this problem of mine. Also, I am pretty new to WPF and XAML and this is my project using these technologies.
Any help would be really appreciated.
Thanks.

Transfer Content value of a UserControl to a Control inside it

I need to extend the bing maps control to be more user MVVM friendly (in specific the ZoomLevel and the BoundingRect properties are not Dependency Properties). I am wrapping the control in a custom usercontrol (I also need to add elements to make other map choices e.g. google maps). I need to transfer the Content Value of the UserControl to the BingMapsControl :
<UserControl x:Class="RevOptWebControls.MVVMMapControl"
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"
mc:Ignorable="d"
xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
xmlns:mCore="clr-namespace:Microsoft.Maps.MapControl.Core;assembly=Microsoft.Maps.MapControl"
d:DesignHeight="300" d:DesignWidth="400"
x:Name="Root">
<Grid x:Name="LayoutRoot" Background="White">
<m:Map CredentialsProvider="Al_H1LepP6chseYMu31RK76El6k4SUkx2KVrxeqobE3rTXooFPieuEJ6qiuA211I"
CopyrightVisibility="Collapsed"
LogoVisibility="Collapsed"
ScaleVisibility="Visible"
NavigationVisibility="Visible"
x:Name="MyMap">
</m:Map>
<ComboBox x:Name="c_MapTypes" HorizontalAlignment="Right" VerticalAlignment="Top" SelectedIndex="0" Height="30" SelectionChanged="MapTypes_SelectionChanged">
<ComboBoxItem>Google Roads</ComboBoxItem>
<ComboBoxItem>Google Aerial</ComboBoxItem>
<ComboBoxItem>Bing Maps Roads</ComboBoxItem>
<ComboBoxItem>Bing Maps Aerial</ComboBoxItem>
<ComboBoxItem>Open Street Maps</ComboBoxItem>
<ComboBoxItem>Yahoo Street</ComboBoxItem>
<ComboBoxItem>Yahoo Aerial</ComboBoxItem>
<ComboBoxItem>Blank Map</ComboBoxItem>
</ComboBox>
</Grid>
</UserControl>
Update : Figured out how to do it. Shared the control source code as well : http://basaratali.blogspot.com/2010/12/mvvm-version-of-bing-maps-with-google.html
Why not try a Custom Control with custom template. Use
`{TemplateBinding Content}`
to bind Content with Map control.
Example:
<Style TargetType="local:MVVMMapControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MVVMMapControl">
<Grid x:Name="LayoutRoot"
Background="White">
<m:Map CredentialsProvider="Al_H1LepP6chseYMu31RK76El6k4SUkx2KVrxeqobE3rTXooFPieuEJ6qiuA211I"
CopyrightVisibility="Collapsed"
LogoVisibility="Collapsed"
ScaleVisibility="Visible"
NavigationVisibility="Visible"
x:Name="MyMap"
Content="{TemplateBinding ContentControl.Content}"></m:Map>
<ComboBox x:Name="c_MapTypes"
HorizontalAlignment="Right"
VerticalAlignment="Top"
SelectedIndex="0"
Height="30"
SelectionChanged="MapTypes_SelectionChanged">
<ComboBoxItem>Google Roads</ComboBoxItem>
<ComboBoxItem>Google Aerial</ComboBoxItem>
<ComboBoxItem>Bing Maps Roads</ComboBoxItem>
<ComboBoxItem>Bing Maps Aerial</ComboBoxItem>
<ComboBoxItem>Open Street Maps</ComboBoxItem>
<ComboBoxItem>Yahoo Street</ComboBoxItem>
<ComboBoxItem>Yahoo Aerial</ComboBoxItem>
<ComboBoxItem>Blank Map</ComboBoxItem>
</ComboBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Class:
public class MVVMMapControl : ContentControl // Notice this inherits from ContentControl for its Content Property
{
public MVVMMapControl()
{
this.DefaultStyleKey = typeof(MVVMMapControl);
}
}

WPF staticresource references to Logical Resources in DataTemplates not resolving at runtime

Have I missed something in the step up from .net 3.5 to .net 4 because I'm seeing seemingly buggy behaviour that seems contrary to the goal of the system.
I am trying to drum up a simple MVVM library for work using a few examples. I am consuming it within a Twitter client application for some additional learning and have hit a big stumbling block.
The scenario is this. My root ViewModel (TwitterClientViewModel) object is given an instance of a DialogViewModel object for display. The DialogViewModel is added to a collection and a bool HasDialogs is set to true. PropertyChanged events are invoked for the collection and the flag if necessary. This part works fabulously.
The view for TwitterClientViewModel is called TwitterClientTemplate and makes Visible an overlay for DialogViewTemplate (DialogViewModel's view) hosting. The hosting ContentControl's template references DialogViewTemplate with a DynamicResource extension. This displays great in the designer and at runtime.
This is where things get strange. The 'body' of DialogViewTemplate hosts dialog content with a further content control bound to DialogViewModel.Content (type object). The hope was that with use of a TemplateSelector (of which I wrote a nice declarative one, but have commented out for testing purposes) I could display both text and interactive elements. For example, requesting details from the user when authenticating a Twitter account. In this case, a PIN number.
At this point I have a two nested contentcontrols for the dialog implementation. For testing purposes, the contentcontrol in the body of DialogViewTemplate uses a staticresource extension to retrieve EnterPINDialogTemplate (view for EnterPINDialogViewModel). Both EnterPINDialogTemplate and DialogViewTemplate are in the same file (the former is defined first of course) although originally they were separate.
At runtime the staticresource extension throws a XamlParseException with the message;
'Provide value on 'System.Windows.Markup.StaticResourceHolder' threw an exception.'
and an inner exception message;
'Cannot find resource named 'EnterPINDialogTemplate'. Resource names are case sensitive'
Using a dynamicresource returns null and displays the Fullname of the EnterPINDialogViewModel type in the contentcontrol - as expected when the resource is not resolved. Breaking into my custom TemplateSelector as calling FrameWorkElement.FindResource() throws a similar exception (TryFindResource returns null).
My first thought was that the logical tree is split when the datatemplates are constructed and I remembered an issue in that area from an earlier project. I tried using the MergeDictionaries property of ResourceDictionary to make the resource dictionaries avaliable from within the DataTemplate but the designer did not like that one bit, and the error is described here:
http://connect.microsoft.com/VisualStudio/feedback/details/498844/wpf-designer-throws-invalidcastexception
Scratch that idea. I have tried merging the dictionaries at Application, Window and TwitterClientTemplate levels but have had no luck.
Below are the xaml files.
DialogTemplates.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:VM="clr-namespace:EpicTweet.ViewModel"
xmlns:ET="clr-namespace:EpicTweet"
xmlns:T="clr-namespace:EpicTweet.Tools"
xmlns:MV="clr-namespace:MVVM;assembly=MVVM"
xmlns:Loc="clr-namespace:EpicTweet.Localization"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<DataTemplate DataType="VM:EnterPINDialogViewModel" x:Key="EnterPINDialogTemplate">
<Grid d:DesignWidth="453.89" d:DesignHeight="78.92" Loc:ResXManagerProperty.ResourceManager="{x:Static ET:Language.ResourceManager}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Content="{Loc:ResxExtension ResourceName=String_PIN, FallbackValue='<PIN>'}"/>
<TextBox Grid.Column="1"/>
<TextBlock Grid.Row="1" Grid.RowSpan="2"></TextBlock>
</Grid>
</DataTemplate>
<DataTemplate x:Key="DialogViewTemplate" DataType="MV:DialogViewModel">
<Border BorderBrush="Black" BorderThickness="1">
<Grid d:DesignWidth="277.419" d:DesignHeight="74.96" Background="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" Height="Auto" Width="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border d:LayoutOverrides="Width, Height" BorderThickness="0,0,0,1" BorderBrush="Black">
<Label Content="{Binding DisplayName, FallbackValue=Header}" VerticalAlignment="Center" HorizontalAlignment="Left"/>
</Border>
<ContentControl Content="{Binding Content, FallbackValue=Body}" ContentTemplate="{StaticResource EnterPINDialogTemplate}" HorizontalAlignment="Stretch" d:LayoutOverrides="Height" Grid.Row="1" Margin="5">
<!--<ContentControl.ContentTemplateSelector>
<T:TypeTemplateSelector>
<T:TemplateTypeRelationship Type="{x:Type VM:EnterPINDialogViewModel}" ResourceKey="EnterPINDialogTemplate"/>
</T:TypeTemplateSelector>
</ContentControl.ContentTemplateSelector>-->
</ContentControl>
<ItemsControl Grid.Row="2" Margin="10"
ItemsSource="{Binding Commands, Mode=OneTime, FallbackValue={x:Static VM:TwitterClientViewModel.DEFAULT_DIALOG_COMMANDS}}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button
Content="{Binding DisplayName, FallbackValue=CommandName, Mode=OneWay}"
Command="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</Border>
</DataTemplate>
TwitterClientDataTemplate.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:VM="clr-namespace:EpicTweet.ViewModel"
xmlns:ET="clr-namespace:EpicTweet"
xmlns:MV="clr-namespace:MVVM;assembly=MVVM"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="DialogTemplates.xaml"/>
</ResourceDictionary.MergedDictionaries>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<DataTemplate x:Key="TwitterClientTemplate" DataType="MV:TwitterClientViewModel">
<ScrollViewer d:DesignWidth="285.083" d:DesignHeight="119.96">
<Grid>
<StackPanel d:LayoutOverrides="Width, Height">
<StackPanel Orientation="Horizontal">
<Button Command="{Binding AddAccountCommand.Command}" Content="{Binding AddAccountCommand.DisplayName, FallbackValue=<Add Account>}"/>
</StackPanel>
<ContentControl/>
</StackPanel>
<Border BorderThickness="1" Background="#80000000" Visibility="{Binding HasDialogs, Converter={StaticResource BooleanToVisibilityConverter}, FallbackValue=Collapsed, Mode=OneWay}">
<Grid VerticalAlignment="Stretch" MinWidth="50" MaxWidth="200">
<ContentControl Content="{Binding Dialogs[0], Mode=OneWay}" ContentTemplate="{DynamicResource DialogViewTemplate}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
</Grid>
</ScrollViewer>
</DataTemplate>
Help me stackoverflow, you're my only hope!
EDIT: Did some further work on this issue. If both templates are in the same file dynamicresource and staticresource extensions both resolve the resource without issue. If they are in separate files, the resource will not resolve regardless of how I merge the dictionaries; each extension returns null.
Obviously the solution is to throw both resources into the same dictionary but as far as I'm concerned this is a hack and is not intended behaviour of the logical resource lookup system. I am not a happy bunny right now. This seems pretty undocumented...
If ever there was a pratt, it is me. After 4 hours on a Friday night trying to solve this one I have cracked it, no thanks to what I can only call flaky error reporting.
Here is the buzz.
<DataTemplate x:Key="TwitterClientTemplate" DataType="MV:TwitterClientViewModel">
should be
<DataTemplate x:Key="TwitterClientTemplate" DataType="{x:Type MV:TwitterClientViewModel}">
And bam, it works.
My big gripe remains however. Why does the incorrect syntax work in the designer but not at runtime? My guess is because runtime optimization just doesn't bother to populate a dictionary with poorly authored xaml but it would be nice to get a warning that it is wrong.

Resources