I have a WPF application that should be used on a touch screen. I have been asked to play a sound when a button is pressed on the screen, for the whole application.
My idea was to create a style to do this, include the resource dictionnary in my app.It works quite well.
However, this style is in a separate DLL and I would like my main application to change the path of the sound file (BoutonClickSound Url below). But I could not find a way to do it.
I have tried several ugly things like :
System.Windows.Application.Current.Resources.MergedDictionaries[0]["BoutonClickSound"] = new Uri(m_MainVM.ButClickSoundPath);
System.Windows.Application.Current.Resources.MergedDictionaries[0].MergedDictionaries[0]["BoutonClickSound"] = new Uri(m_MainVM.ButClickSoundPath);
But none of them seems to work...
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=PresentationFramework"
xmlns:sys="clr-namespace:System;assembly=System">
<sys:Uri x:Key="BoutonClickSound">c:\buttonclick.wav</sys:Uri>
<Style TargetType="{x:Type FrameworkElement}" x:Key="SoundButton">
<Style.Triggers>
<EventTrigger RoutedEvent="PreviewMouseDown">
<SoundPlayerAction x:Name="SoundPlayer" Source="{DynamicResource BoutonClickSound}" />
</EventTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type primitives:Selector}" x:Key="SoundSelectionChange">
<Style.Triggers>
<EventTrigger RoutedEvent="SelectionChanged">
<SoundPlayerAction x:Name="SoundPlayer" Source="{DynamicResource BoutonClickSound}" />
</EventTrigger>
</Style.Triggers>
</Style>
Any idea how to do this ?
Thank you.
Just declare a local resource with the same key.
If you want it globally in your application, you can add it to a MergedDictionary after you include the MergedDictionary from your library.
Add another entry like this:
<sys:Uri x:Key="BoutonClickSound">c:\differentfile.wav</sys:Uri>
And it should cause your style to use that file instead.
Edit:
To set the resource in the code-behind, first you must add it to the local resource dictionary:
Resources.Add("BoutonClickSound", new Uri("your uri here"));
After you add it, if you want to later change it, you can't re-add it, you have to modify it:
Resources["BoutonClickSound"] = new Uri("your uri here");
Related
I'm trying to add a resource dictionary to a page but I keep getting a designer error in my xaml. The app runs fine with no issue but the designer error bothers me.
Here's how I did it. Both works fin at run time. But it's saying Failed to set "Source". Any clues?
That also gives an error to all the static resource I used from the resource dictionary.
Update:
This is another approach. Instead of directly adding it to the Page's resources, I added it to the Application.Resources still cant resolve the styles. I'm using VS2017 v15.4.4
Steps to reproduce:
List item
Create a new UWP Application Project (App1)
Create a new UWP Class Library (ClassLibrary1)
In ClassLibrary1, add a new ResourceDictionary (Dictionary1.xaml).
In Dictionary1.xaml, add a Style, let's say a button style.
<Style TargetType="Button" x:Name="ButtonStyle1" x:Key="ButtonStyle1">
<Setter Propeprty="Background" Value="Red" />
</Style>
In the ClassLibrary1, add a new BlankPage (BlankPage1)
In the BlankPage1, add a button and use ButtonStyle1
`
In App1, merge the resource dictionary to App.Resources (inside App.xaml).
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionary>
<ResourceDictionary Source="ms-appx:///ClassLibrary1/Dictionary1.xaml" />
</ResourceDictionary.MergedDictionary>
</ResourceDictionary>
</Application.Resources>
Make the BlankPage1 the start page, go to App.xaml.cs and and change MainPage to BlankPage1:
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(BlankPage1), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
}
Run the application. It will run just fine. But the problem is in the designer where it cannot recognize the style from the resource dictionary.
I followed your steps and found a typo and an issue.
The typo: In Style step (Perhaps only in the sample), There is typo in the word 'Proeprty':
<Style TargetType="Button" x:Name="ButtonStyle1" x:Key="ButtonStyle1">
<Style.Setters>
<Setter Property="Background" Value="Red" />
</Style.Setters>
</Style>
The issue in the way you are merging dictionary, it should be using the following syntax:
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
After fixing both issues, Visual studio designer didn't complain about anything.
Did it fix the issue for you? If not then your steps to reproduce aren't complete.
I'm trying to implement 2 different themes for a WPF Application. I found this excellent post by #bendewey:
"Can WPF themes be used to include multiple skins for an application that can be changed at runtime?"
And have used it to implement two themes. I have created two Resource Folders, Lets call them ResourcesTheme1 and ResourcesTheme2 and Two Xaml Resource Dictionary files (Style1.xaml & Style2.xaml) that have the styles.
With this I have been able to set the following styles:
In Style1.xaml
<Style x:Key="HomeViewBackGroundImage" TargetType="Image">
<Setter Property="Source" Value="/ResourcesTheme1/Background.png" />
</Style>
In Style2.xaml
<Style x:Key="HomeViewBackGroundImage" TargetType="Image">
<Setter Property="Source" Value="/ResourcesTheme2/Background.png" />
</Style>
And this has worked a treat for me (if there's a better way please feel free to suggest it).
No the problem I have is that within my mainPage xaml I want to put on a row of buttons and each button has it's own image that it get's from binding to an ObservableCollection. I would like the Binding to look into the correct resource folder, but don't know how to make it happen without writing code behind.
So what I have is the following Binding:
<Image Name="ContentImage" Source="{Binding ImageName}" Stretch="UniformToFill">
And the following code behind:
if (useTheme1)
{
imageName = "/PlayingWithThemes;component/ResourcesTheme1/" + imageFileName;
}
else
{
imageName= "/PlayingWithThemes;component/ResourcesTheme2/" + imageFileName;
}
Any thoughts on how I could make the source for the image something like:
Source="ResourceFoler + {Binding ImageName}"
Or is there something more generic than:
/PlayingWithThemes;component/ResourcesTheme1/"
That I could use.
Thanks in advance.
A
I have a back button which is copied almost to all the Controls in my application.
I have set the styles and properties of the button on each individual control (usercontrol)
Now I want to change the text property of the button of all the control (usercontrol).
I don't want to go and change the property of each control.
Please help me setting a global property which sets the property in one place.
Since the style is common to all pages. Create the style without a key/name, just the target type would do.
<Style TargetType="{x:Type Button}">
Then do either of the following -
Add it to the App.XAML for visibility throughout the app
Better approach would be to define a resource dictionary file and import it, wherever you need it.
<Style TargetType="{x:Type Button}">
<Setter Property="Text" Value="{Binding text}" />
<Setter Property="...." Value="{Binding ....}"/>
</Style>
Add this to App.xaml file as you want it to be global style for all your user controls.
I have a ControlTemplate that is used on 9 Buttons (a tic tac toe field in this case)
The purpose is to have an additional animation that turns a Button red after the game has ended. The Template is defined in App.xaml and used in Spiel.xaml.cs. The Buttons using this Template are created in the code, not using the Spiel.xaml file.
<Application.Resources>
<ControlTemplate x:Key="MatrixElement" TargetType="Button">
<Border x:Name="MatrixElementBorder" BorderBrush="White" Margin="0,0,0,0" Width="140" Height="140">
<Border.Background>
<SolidColorBrush x:Name="MatrixElementBackgroundBrush" Color="LightBlue"/>
</Border.Background>
<Border.Resources>
<Storyboard x:Key="storyBoardOnWin">
<ColorAnimation
Storyboard.TargetName="MatrixElementBorder"
Storyboard.TargetProperty="(Border.Background)"
From="DarkBlue"
To="DarkRed"
Duration="0:0:2" />
</Storyboard>
</Border.Resources>
</Border>
</ControlTemplate>
...
</Application.Resources>
I can't find a way to access the storyBoardOnWin animation in my code.
I tried accessing it via Application.Current.Resources["storyBoardOnWin"];
but that returns a nullPointer. How can I access the Template's Resources in the code behind?
The solution to your problem is that you've marked the storyBoardOnWin property as a Key in the Border's Resources dictionary. If you marked is as a Name instead, it can be called directly in your codebehind.
In other words, you have this:
<Storyboard x:Key="storyBoardOnWin">
You can do this instead:
<Storyboard x:Name="storyBoardOnWin">
and call it from the code behind just like so:
page.xaml.cs
...
storyBoardOnWin.Begin();
...
Hope that helps! I'm not sure how you're using the ControlTemplate i.e. if it's defined as a resource in its own file so if it is, this probably won't work.
You cannot access the resource, because it is not a resource of App.Resources. It is a resource of a control that is a resource of App.Resouces.
I'm guessing that you already have the button when you are trying to get the animation (maybe through a button click event or something) so try the following:
var border = (Border)VisualTreeHelper.GetChild(button,0);
var story = (Storyboard)border.Resources["storyBoardOnWin"];
I'm working on an application that had many infrgistics XamDataGrids. I'd like to at least provide Copy to clipboard abilities on them. This can easily be achieved in the XAML for each grid, with:
<igDP:XamDataGrid DataSource="{Binding}" >
<igDP:XamDataGrid.FieldLayoutSettings>
<igDP:FieldLayoutSettings AllowClipboardOperations="Copy"/>
</igDP:XamDataGrid.FieldLayoutSettings>
</igDP:XamDataGrid>
However, I would like all XamDataGrids in the application to allow this Copy to clipboard feature. I thought styling would be the answer, but for some reason, this does not work:
<Style TargetType="{x:Type igDP:FieldLayoutSettings}">
<Setter Property="AllowClipboardOperations" Value="Copy" />
</Style>
I've tried many variations on the above, but nothing seems to take, and there are no error messages. Any help would be really appreciated.
This is untested but perhaps you require the fully qualified name as below: (including the XamDataGrid.)
<Style TargetType="{x:Type igDP:XamDataGrid.FieldLayoutSettings}">
<Setter Property="AllowClipboardOperations" Value="Copy" />
</Style>
This question is old, but I just ran across it.
Anyway, the TargetType of your style will be XamDataGrid.
The property you are setting is FieldLayoutSettings.
<Style TargetType="{x:Type igDp:XamDataGrid}">
<Setter Property="FieldLayoutSettings">
<Setter.Value>
<igDp:FieldLayoutSettings AllowClipboardOperations="Copy"/>
</Setter.Value>
</Setter>
</Style>
Is this style defined in a place (like App.xaml) where every XamDataGrid can inherit it?
Have you tried defining this style in the same XAML file as a XamDataGrid that might use it? I would start by seeing if you could make this work as a local style in one specific place.