How Bind a property to ApplicationRessource located in App.xaml - c#

I created a CParametres object in my app.xaml.cs like this :
public partial class App : Application
{
public CParametres myParamObject;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
myParamObject = new CParametres(System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) +#"\BingMapsParam.ini");
if (myParamObject.LoadParams() == false)
{
return;
}
Resources.Add("myParamObject", myParamObject);
}
}
Now, in my app.xaml, i add a Dictionnary :
<Application x:Class="myGeoloc.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="MyDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
And, here is my Dictionnary :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:t="clr-namespace:myGeoloc"
xmlns:m="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF">
<t:CParametres x:Key="myParamObject"/>
<Style TargetType="m:Pushpin" x:Key="PushpinStyle_Fournisseur">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="m:Pushpin" >
<!-- <Image Stretch="Fill" Source="C:\Users\FabioWalter\Documents\Visual Studio 2013\Projects\myGeoloc\myGeoloc\bin\Debug\Pushpins\PushPinStandard.png" />-->
<Image Stretch="Fill" Source="{Binding Path=strPicturePushpinFournisseur, Source={StaticResource myParamObject}}" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Width" Value="64" />
<Setter Property="Height" Value="64" />
</Style>
</ResourceDictionary>
strPicturePushpinFournisseur is string in CParametres. This string contain the picture paths.
Actually, the image don't display and it's related to my bad binding.
Anyone could help me please ?
Any ideas ?
Thanks a lot :)

You can do some thing like this:
To put the object in the resource dictionary for making it available to the rest of the application
<Application x:Class="SomeNameSpace.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:t="clr-namespace:SomeNameSpace.NameSpaceForT"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="View/DictionaryResources/MainResourceDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
<t:CParametres x:Key="myParamObject"/>
</ResourceDictionary>
</Application.Resources>
</Application>
Make a binding to any object's property (This is a sample):
<Window x:Class="SomeNameSpace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:View="clr-namespace:SomeNameSpace.View"
Title="MainWindow"
DataContext="{Binding Path=strPicturePushpinFournisseur, Source={StaticResource myParamObject}}"
Height="350" Width="525">
...
EDIT
You can create the object in the App.xaml.cs file, and add contructor parameters in this way:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Resources.Add("myParamObject", new CParametres ("Param1", "Param2"));
}
}
And use it in this way:
<TextBlock Text="{Binding Path=strPicturePushpinFournisseur, Source={StaticResource myParamObject}}"></TextBlock>
Hope it helps...

Related

Using C#, how to access a control inside WPF ResourceDictionary

I have a ResourceDictionary to define my custom Window style. I am using WindowChrome to style my MainWindow by adding a custom title bar to it that has a button control. Question: Using C# in the code behind file MainWindow.cs, how can I access the button control btnTest residing inside the following MyWindowChrome.xaml file:
MyWindowChrome.xaml:
<ResourceDictionary x:Class="MyWPFProject.WindowStyle"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyWPFProject">
<Style x:Key="CustomWindowStyle" TargetType="{x:Type Window}">
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome ResizeBorderThickness="5" UseAeroCaptionButtons="False" />
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid>
<DockPanel>
<Button x:Name="btnTest" WindowChrome.IsHitTestVisibleInChrome="True"/>
</DockPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
App.xaml
<Application x:Class="MyWPFProject.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:main="clr-namespace:MyWPFProject"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MyWPFProject;component/WindowStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
You didn't show how/when you apply the Style. Assuming that you set the FrameworkElement.Style directly in the XAML file, you should be able to get the template elements when FrameworkElement.Loaded was raised:
MainWindow.xaml.cs
partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
var button = this.Template.FindName("btnTest", this) as Button;
}
}

Where can I put the EventSetter so that its handler is searched in the Control's code-behind, not in the resource dictionary's?

I have a template with a Style that uses an EventSetter to set a common event handler to some Hyperlinks. But I want to handle this event not in the resource dictionary's .cs file but in the custom control's .cs file. How can I do this? I am in the process of moving resources into theme .xaml files. I thought about separating the functionality part of the Hyperlink style, but where should I put the event setter? I thought I can use commands, but is there a more concise tehnique that does not require changing each Hyperlink element and works for elements that do not support commands?
I use .NET Framework 4.7.2. I have made a few searches over the web and a simple test example:
App.xaml
<Application x:Class="wpf_test_2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:wpf_test_2"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Dictionary.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:wpf_test_2">
<ControlTemplate x:Key="MyControlTemplate">
<ControlTemplate.Resources>
<Style TargetType="Button">
<!-- obviously, this does not compile: -->
<EventSetter Event="Click" Handler="MyHandler"/>
</Style>
</ControlTemplate.Resources>
<UniformGrid Rows="5" Columns="5">
<Button>A</Button>
<Button>B</Button>
<Button>C</Button>
<Button>D</Button>
<Button>E</Button>
<Button>F</Button>
<Button>G</Button>
<Button>H</Button>
<Button>I</Button>
</UniformGrid>
</ControlTemplate>
</ResourceDictionary>
MainWindow.xaml
<Window x:Class="wpf_test_2.MainWindow"
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:local="clr-namespace:wpf_test_2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<local:MyControl/>
</Grid>
</Window>
MyControl.xaml
<Control x:Class="wpf_test_2.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:wpf_test_2"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Template="{DynamicResource MyControlTemplate}">
</Control>
MyControl.xaml.cs
/// <summary>
/// Interaction logic for MyControl.xaml
/// </summary>
public partial class MyControl : Control
{
public MyControl()
{
InitializeComponent();
}
private void MyHandler(object sender, RoutedEventArgs e)
{
var b = sender as Button;
MessageBox.Show($"Button {b.Content.ToString()} was clicked!");
}
}
Screenshot
Expected: the project compiles, and when I click one of the buttons, a MessageBox appears with the content of the button as string.
Actual: the project does not compile.
Thank you.
Inspired by Clemens' comment, I created a RoutedUICommand, a corresponding command binding, and setters which set Command and CommandParameter:
AboutWindow.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:cs_timed_silver"
x:Class="cs_timed_silver.AboutWindow"
mc:Ignorable="d"
Width="448" Height="200" ResizeMode="NoResize"
WindowStartupLocation="CenterOwner"
Loaded="Window_Loaded"
Closed="Window_Closed"
Style="{DynamicResource AboutWindowStyle}">
<Window.CommandBindings>
<CommandBinding Command="{x:Static local:AboutWindow.NavigateCommand}"
CanExecute="CommandBinding_CanExecute"
Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
</Window>
AboutWindow.xaml.cs
public partial class AboutWindow : Window
{
public static RoutedUICommand NavigateCommand { get; set; } =
new RoutedUICommand("", "NavigateCommand", typeof(AboutWindow));
[...]
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
System.Diagnostics.Process.Start(
new System.Diagnostics.ProcessStartInfo((e.Parameter as Uri).AbsoluteUri));
}
Light.xaml
<Style x:Key="AboutWindowStyle" TargetType="local:AboutWindow">
[...]
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<ControlTemplate.Resources>
[...]
<Style TargetType="{x:Type Hyperlink}">
<Setter Property="Command" Value="{Binding NavigateCommand}"/>
<Setter Property="CommandParameter"
Value="{Binding RelativeSource={RelativeSource Mode=Self}, Path=NavigateUri}"/>
</Style>
</ControlTemplate.Resources>
[...]

"Value cannot be null" error in App.xaml with ResourceDictionary (WPF)

Using .NET Framework 4.6.1 and I'm using a UI kit that I've installed via NuGet and they are referenced correctly in the project.
App.xaml
<Application x:Class="ExampleApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI"
xmlns:local="clr-namespace:ExampleApp"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="{x:Static adonisUi:ResourceLocator.DarkColorScheme}" />
<ResourceDictionary Source="{x:Static adonisUi:ResourceLocator.ClassicTheme}" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
MainWindow.xaml
<Window x:Class="ExampleApp.MainWindow"
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:local="clr-namespace:ExampleApp"
mc:Ignorable="d"
Title="MainWindow"
Height="450"
Width="800">
<Window.Style>
<Style TargetType="Window"
BasedOn="{StaticResource {x:Type Window}}" />
</Window.Style>
<Grid>
<StackPanel Margin="10">
<Button Content="Click Me"
HorizontalAlignment="Center" />
</StackPanel>
</Grid>
</Window>
Issues:
<ResourceDictionary Source="{x:Static adonisUi:ResourceLocator.DarkColorScheme}" />
<ResourceDictionary Source="{x:Static adonisUi:ResourceLocator.ClassicTheme}" />
Both lines in App.xaml are getting the following error:
Value cannot be null. Parameter name: item.
I have tried multiple fresh projects, building and rebuilding and I keep getting this error. I am able to build the project and I can see the styles from the UI kit correctly applied on MainWindow even though the error is still there.
However the styles don't appear on the designer window, I'm not sure if it's related to the error I'm getting or not.
Any ideas what could cause this?
I just tried it and it does the same thing to me... using Visual Studio Enterprise 2017 15.9.7
If you look at AdonisUI.ResourceLocator in a decompiler (I used Telerik's JustDecompile), you'll see the definitions:
public static Uri ClassicTheme
{
get
{
return new Uri("pack://application:,,,/AdonisUI.ClassicTheme;component/Resources.xaml", UriKind.Absolute);
}
}
public static Uri DarkColorScheme
{
get
{
return new Uri("pack://application:,,,/AdonisUI;component/ColorSchemes/Dark.xaml", UriKind.Absolute);
}
}
public static Uri LightColorScheme
{
get
{
return new Uri("pack://application:,,,/AdonisUI;component/ColorSchemes/Light.xaml", UriKind.Absolute);
}
}
If you change your App.xaml to reference using these values then it works.
<ResourceDictionary Source="pack://application:,,,/AdonisUI.ClassicTheme;component/Resources.xaml" />
<ResourceDictionary Source="pack://application:,,,/AdonisUI;component/ColorSchemes/Dark.xaml" />

Resource Dictionary not working - Exception raised for Name/Key not found

I have just started working with Resource Dictionaries and I am stuck on this because my resource dictionary is not working at all. I have tried code-behind and XAML but every time I get exceptions and the app crashes.
If I reference the Dictionary through XAML I get the exception at runtime that Name/Key is not found. The code I used in App.xaml is:
<Application
x:Class="WatchfreeWebsite.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WatchfreeWebsite.Helpers">
<Application.Resources>
<TransitionCollection x:Key="TransCollection">
<EdgeUIThemeTransition Edge="Right"/>
</TransitionCollection>
<ResourceDictionary x:Key="resourcesDictionary">
<ResourceDictionary.MergedDictionaries>
<local:GlobalTemplates Source="Helpers/GlobalTemplates.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
The resource dictionary holds aDataTemplate and a MediaTransportControlsStyle but I cant seem to reference it through XAML because it gives syntax errors and during the runtime the page produces exception while loading XAML at InitializeComponent(); stage.
Resource Dictionary:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WatchfreeWebsite.Helpers"
x:Class="WatchfreeWebsite.Helpers.GlobalTemplatesClass"
xmlns:data="using:WatchfreeWebsite.Helpers">
<DataTemplate x:Key="StreamBoxItemTemplate"
x:DataType="data:StreamingHelper">
<TextBlock Text="{x:Bind StreamName, Mode=OneWay}"
Style="{StaticResource BodyTextBlockStyle}"
TextWrapping="NoWrap"
MaxLines="1"
TextTrimming="WordEllipsis"/>
</DataTemplate>
<Style TargetType="MediaTransportControls"
x:Key="myCustomTransportControls">
<Setter Property="IsTabStop" Value="False" />
.......
</Style>
</ResourceDictionary>
The class behind the resource dictionary is:
public partial class GlobalTemplatesClass
{
public GlobalTemplatesClass()
{
this.InitializeComponent();
}
}
I reference the DataTemplate inside the above style and this style is referenced in another page as:
<MediaPlayerElement x:Name="MediaView"
Grid.Row="2"
Source="{Binding MediaSourceObject, Mode=OneWay}"
DoubleTapped="MediaView_DoubleTapped"
AreTransportControlsEnabled="True">
<MediaPlayerElement.TransportControls>
<data:CustomTransportControlsHelper Style="{StaticResource ResourceKey=myCustomTransportControls}"/>
</MediaPlayerElement.TransportControls>
</MediaPlayerElement>
But this is not working and there is a red line below the resource name saying that the resource is not found.
Is there something that I am missing? If someone can help me here please provide your suggestions. Thanks
When you add multiple items under your resources, each of them should fall within the <ResourceDictionary> tag and not directly under <Application.Resources>.
That's because Resources itself is a dictionary, so you're in effect trying to replace that collection rather than add elements to it. Docs here: https://msdn.microsoft.com/en-us/library/system.windows.application.resources%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
I created a sample project with just an App.xaml at the project base level, a folder called Helpers and a ResourceDictionary under Helpers named GlobalTemplates.xaml to match yours.
Created a simple brush as an example in GlobalTemplates.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1.Helpers">
<SolidColorBrush x:Key="DefaultForeground" Color="DarkGreen" />
</ResourceDictionary>
In App.xaml
<Application
x:Class="App1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
RequestedTheme="Light">
<Application.Resources>
<ResourceDictionary>
<TransitionCollection x:Key="TransCollection">
<EdgeUIThemeTransition Edge="Right"/>
</TransitionCollection>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Helpers/GlobalTemplates.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
And then in MainPage.xaml successfully referenced the style from the dictionary:
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock Foreground="{StaticResource DefaultForeground}">Hello world</TextBlock>
</Grid>
</Page>

To call converter from ControlTemplate string

I'm trying to bind controlTemplate to in generic.xaml.My controlTemplate has converter in it.While binding,its throwing an exception as Provide value on 'System.Windows.Markup.StaticResourceHolder' threw an exception.
In MyView.cs
templateString = #"<ControlTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" >
<Canvas><Polygon Points=""{Binding Size,Converter={StaticResource SizeConverter}}"" Fill=""red""/></Canvas>
</ControlTemplate>";
this.Template = XamlReader.Load(new System.Xml.XmlTextReader(new StringReader(templateString ))) as ControlTemplate;
In generic.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:MySample"
xmlns:vsm="clr-namespace:System.Windows;assembly=PresentationFramework"
xmlns:srcview="clr-namespace:MySample.Views"
xmlns:converters="clr-namespace:MySample.Converters"
>
<converters:SizeConverter x:Key="SizeConverter" />
<Style TargetType="{x:Type srcview:MyView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type srcview:MyView}">
<Canvas>
<ContentControl Template="{TemplateBinding Template}" Name="contentControl" >
</ContentControl>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
How to fix this issue??
One normally gets this problem when the static resources are not defined before referencing them.
For a test, try reading an xaml usercontrol with a static resource defined in the resources section of the xaml. If that works then you know the problem is not with referencing the converter, but rather when and were it is defined.
A faster way to ensure that the converter is actually being loaded is to put it in the app.xaml. This will ensure that the resource dictionary is loaded at startup. Here follows an example:
<Application x:Class="TeslaFrame.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:metro="http://schemas.codeplex.com/elysium"
>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Elysium;component/Themes/Generic.xaml"/>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="globalBoolToVisConverter" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

Categories

Resources