For performance and isolation reasons, I have an application that uses cross-process communication, and utilizes System.AddIn.Pipeline.FrameworkElementAdapters.ContractToViewAdapter() and System.AddIn.Pipeline.FrameworkElementAdapters.ViewToContractAdapter() methods to transfer the GUI controls from the plugin processes to the host process.
The plugin GUI controls are mostly Microsoft-provided controls supporting a rehosted Microsoft Workflow Foundation interface. Many of these have hard-coded colors and brushes in their xaml definitions, and are not easily rethemed.
I support two different host applications. One of them has extensive theming via an Application-level ResourceDictionary, and the other does not do any custom theming.
In the application with no custom theming, controls display thusly
But in the application with custom theming, it looks like this
It picks up some of the theme from the host application, but because the Microsoft controls hard-code much of their colors, it's incomplete and looks awful.
I've used Snoop to find the brushes and colors that the themed application is forcing onto these controls, and from that, I made a resource dictionary with the right colors.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:s="clr-namespace:System;assembly=mscorlib">
<Color x:Key="aC03">#FF000000</Color>
<Color x:Key="aC09">#FFFFFFFF</Color>
<Color x:Key="aC10">#FF858C9D</Color>
<Color x:Key="aC11">#FF000000</Color>
<Color x:Key="aC13">#FF8C9097</Color>
<Color x:Key="aC14">#FFFFFFFF</Color>
<Color x:Key="aC15">#FF777D87</Color>
<Color x:Key="aC16">#FF6E7582</Color>
<Color x:Key="aC17">#FFE9ECEE</Color>
<Color x:Key="aC20">#FF000000</Color>
<Color x:Key="aC21">#FF000000</Color>
<GradientStopCollection x:Key="aG01">
<GradientStop Offset="0.00" Color="{StaticResource aC10}" />
<GradientStop Offset="0.10" Color="{StaticResource aC13}" />
<GradientStop Offset="0.49" Color="{StaticResource aC15}" />
<GradientStop Offset="0.50" Color="{StaticResource aC16}" />
<GradientStop Offset="1.00" Color="{StaticResource aC16}" />
</GradientStopCollection>
<SolidColorBrush x:Key="ControlTextBrush" PresentationOptions:Freeze="true" Color="{StaticResource aC03}" />
<SolidColorBrush x:Key="ControlBrush" PresentationOptions:Freeze="true" Color="{StaticResource aC14}" />
<SolidColorBrush x:Key="TextBox_Default_Layer1" PresentationOptions:Freeze="true" Color="{StaticResource aC14}" />
<SolidColorBrush x:Key="TextBox_Default_Layer2" PresentationOptions:Freeze="true" Color="{StaticResource aC21}" />
<SolidColorBrush x:Key="TextBox_Default_Layer3" PresentationOptions:Freeze="true" Color="{StaticResource aC11}" />
<SolidColorBrush x:Key="ComboBox_Default_Layer2" PresentationOptions:Freeze="true" Color="{StaticResource aC20}" />
<LinearGradientBrush x:Key="ComboBox_Default_Layer3" PresentationOptions:Freeze="true" GradientStops="{StaticResource aG01}" StartPoint="0,0" EndPoint="0,1" />
<SolidColorBrush x:Key="ComboBox_Default_Text" PresentationOptions:Freeze="true" Color="{StaticResource aC03}" />
<SolidColorBrush x:Key="WindowBrush" PresentationOptions:Freeze="true" Color="{StaticResource aC17}" />
<SolidColorBrush x:Key="ContextMenu_Layer1" PresentationOptions:Freeze="true" Color="{StaticResource aC09}" />
</ResourceDictionary>
If I apply this resource dictionary to either the root rehosted control, or that and all of its children, it looks like this
So even overriding the resources seems to be insufficient.
Is there a way to suppress/prevent/disable resource inheritance, or do I need to override each and every resource (color, brush, style, template, et.c) that affects my controls?
Edit: The style overriding code was requested. I've tested running the following on the Loaded event and the Initialized event (individually, not together), and running on the GUI thread vs in a task. Calling it on the loaded event produces some change, calling it on the initialized event does not
var resources = new ResourceDictionary { Source = new Uri("pack://application:,,,/WorkflowRemoting;component/Host/ResourceOverride.xaml") };
Action<DependencyObject, ResourceDictionary>
SetResources = null;
SetResources = (element, dictionary) =>
{
DependencyObject[]
children = null;
#if runInTask
Dispatcher.Invoke(() =>
{
#endif
var nChildren = VisualTreeHelper.GetChildrenCount(element);
children = Enumerable.Range(0, nChildren).Select(x => VisualTreeHelper.GetChild(element, x)).ToArray();
#if runInTask
});
#endif
foreach (var child in children)
{
#if runInTask
Dispatcher.Invoke(() =>
{
#endif
var fe = child as FrameworkElement;
if (fe != null)
if (this.Resources == null)
fe.Resources = dictionary;
else
fe.Resources.MergedDictionaries.Add(dictionary);
#if runInTask
});
#endif
SetResources(child, dictionary);
}
};
#if runInTask
Task.Run(() =>
{
#endif
SetResources(this, resources);
#if runInTask
});
#endif
If you are displaying the controls, just zero out the style for each of the controls as such:
<Button Style="{x:Null}" Content="Press me"/>
Related
For a project i'm using the Xceed WPF Toolkit colorpicker to let the users select a color. This colorpicker is used in different pages and with our own custom colors. Therefore i want to create one global style in the Application.xaml and then use the colorpicker on the different pages, however i cannot find a properly working example of how to create a global style WITH an array of StandardColors other that creating it in code and copy/pasting the code onto the differente pages.
Hopefully someone could help me out with this.
The way i got it working now is:
Xaml on every page/usercontrol:
<xctk:ColorPicker
Name="ClrPcker_Background"
Grid.Row="4"
Grid.Column="1"
Width="300"
Margin="3"
HorizontalAlignment="Left"
SelectedColor="{Binding BackgroundColor, Mode=TwoWay, Converter={StaticResource BrushToColor}, UpdateSourceTrigger=PropertyChanged}"
SelectedColorChanged="ClrPcker_Background_SelectedColorChanged"
ShowRecentColors="True" />
Code behind every page/usercontrol:
CustomColorList.Add(New Xceed.Wpf.Toolkit.ColorItem(Color.FromRgb(32, 32, 32), "DarkBackground"))
CustomColorList.Add(New Xceed.Wpf.Toolkit.ColorItem(Color.FromRgb(60, 60, 59), "DarkLightBackground"))
CustomColorList.Add(New Xceed.Wpf.Toolkit.ColorItem(Color.FromRgb(87, 87, 86), "LightGrayBackground"))
CustomColorList.Add(New Xceed.Wpf.Toolkit.ColorItem(Color.FromRgb(231, 76, 60), "RedLight"))
CustomColorList.Add(New Xceed.Wpf.Toolkit.ColorItem(Color.FromRgb(39, 174, 96), "GreenLight"))
CustomColorList.Add(New Xceed.Wpf.Toolkit.ColorItem(Color.FromRgb(52, 152, 219), "BlueLight"))
CustomColorList.Add(New Xceed.Wpf.Toolkit.ColorItem(Color.FromRgb(243, 156, 18), "OrangeLight"))
CustomColorList.Add(New Xceed.Wpf.Toolkit.ColorItem(Color.FromRgb(104, 34, 27), "RedDark"))
CustomColorList.Add(New Xceed.Wpf.Toolkit.ColorItem(Color.FromRgb(25, 110, 61), "GreenDark"))
CustomColorList.Add(New Xceed.Wpf.Toolkit.ColorItem(Color.FromRgb(22, 64, 92), "BlueDark"))
CustomColorList.Add(New Xceed.Wpf.Toolkit.ColorItem(Color.FromRgb(116, 74, 9), "OrangeDark"))
Idealy i can also use our global UsedColors as ColorItems that are also added to the Application.xaml
<!-- Background colors -->
<Color x:Key="clrDarkBackground">#202020</Color>
<Color x:Key="clrDarkLightBackground">#3C3C3B</Color>
<Color x:Key="clrLightGrayBackground">#575756</Color>
<SolidColorBrush x:Key="scbDarkBackground" Color="{StaticResource clrDarkBackground}" />
<SolidColorBrush x:Key="scbDarkLightBackground" Color="{StaticResource clrDarkLightBackground}" />
<SolidColorBrush x:Key="scbLightGrayBackground" Color="{StaticResource clrLightGrayBackground}" />
<!-- Light Colors -->
<Color x:Key="clrRedLight">#E74C3C</Color>
<Color x:Key="clrGreenLight">#27AE60</Color>
<Color x:Key="clrBlueLight">#3498DB</Color>
<Color x:Key="clrOrangeLight">#F39C12</Color>
<SolidColorBrush x:Key="scbRedLight" Color="{StaticResource clrRedLight}" />
<SolidColorBrush x:Key="scbGreenLight" Color="{StaticResource clrGreenLight}" />
<SolidColorBrush x:Key="scbBlueLight" Color="{StaticResource clrBlueLight}" />
<SolidColorBrush x:Key="scbOrangeLight" Color="{StaticResource clrOrangeLight}" />
<!-- Dark Colors -->
<Color x:Key="clrRedDark">#68221B</Color>
<Color x:Key="clrGreenDark">#196E3D</Color>
<Color x:Key="clrBlueDark">#16405C</Color>
<Color x:Key="clrOrangeDark">#744A09</Color>
<SolidColorBrush x:Key="scbRedDark" Color="{StaticResource clrRedDark}" />
<SolidColorBrush x:Key="scbGreenDark" Color="{StaticResource clrGreenDark}" />
<SolidColorBrush x:Key="scbBlueDark" Color="{StaticResource clrBlueDark}" />
<SolidColorBrush x:Key="scbOrangeDark" Color="{StaticResource clrOrangeDark}" />
You should consider creating a custom control that inherits from ColorPicker instead of having to add items to a list of every view.
You can then for example add the colours to the control in its constructor.
I have a ResourceDictionary for Colors:
<ResourceDictionary>
<Color x:Key="Ori">#000000</Color>
</ResourceDictionary>
Then use DynamicResource to reference them:
<DynamicResource x:Key="Ref", ResourceKey="Ori" />
When over 2 properties bind to Ref:
<SomeControl1.Background>
<SolidColorBrush Color="{StaticResource Ref}">
</SomeControl1.Background>
<SomeControl2.Background>
<SolidColorBrush Color="{StaticResource Ref}">
</SomeControl2.Background>
It would cause when running:
"Ref" is not a valid value for property "Color"
I guess that's because they're both TwoWay Bindings.
Any method to fix?
You can simply do it in that way:
<ResourceDictionary>
<Color x:Key="Ori">#000000</Color>
</ResourceDictionary>
Your controls:
<SomeControl1.Background>
<SolidColorBrush Color="{DynamicResource Ori}">
</SomeControl1.Background>
<SomeControl2.Background>
<SolidColorBrush Color="{DynamicResource Ori}">
</SomeControl2.Background>
Using also StaticResource is weird.
I have a quick question: I want to bind a Solidcolorbrush, which is located in App.xaml's Resources. It has a key assigned to it, but how would I bind to that property from another page?
Here is the App.xaml itself:
<Application x:Class="Mplayer.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>
<Color x:Key="PrimaryAccentColor" A="255" R="3" G="169" B="244"/>
<SolidColorBrush x:Key="PrimaryAccentBrush" Color="{StaticResource PrimaryAccentColor}"/>
<Color x:Key="SecondaryAccentColor" A="255" R="3" G="169" B="244"/>
<SolidColorBrush x:Key="SecondaryAccentBrush" Color="{StaticResource SecondaryAccentColor}"/>
<Color x:Key="LightBackgroundColor" A="255" R="3" G="169" B="244"/>
<SolidColorBrush x:Key="LightBackgroundBrush" Color="{StaticResource LightBackgroundColor}"/>
<Color x:Key="DarkBackgroundColor" A="255" R="3" G="169" B="244"/>
<SolidColorBrush x:Key="DarkBackgroundBrush" Color="{StaticResource DarkBackgroundColor}"/>
</ResourceDictionary>
</Application.Resources>
If I then have a page which I want to bind to the PrimaryAccentColorBrush, how would that bind look?
I tried setting the bind to {Binding Path={StaticResource PrimaryAccentColorBrush}}, but it did not locate it.
Any help would be appreciated =)
You don't have to use Binding, just use StaticResource, like you already do:
Property="{StaticResource PrimaryAccentBrush}"
You almost had it... try this instead:
<TextBlock Background="{Binding Source={StaticResource PrimaryAccentColorBrush}}" />
Although you don't seem to have a PrimaryAccentColorBrush in your example... did you mean PrimaryAccentBrush?
It should be very easy to do this but I haven't found the information that I need. What I want is as simple as changing the color of the slider bar:
I'm using ModernUI and the default bar color is very similar to my background and I want to make it a bit lighter.
You should be able to change it editing the template.
Right click your Slider, Edit Template -> Edit Copy.;.
A new window will appear asking you where VS should put the XAML code for the ControlTemplate and Styles. Chek the tags and such.
Good luck!
Edit:
Ok, here it goes.
Assuming that you already have a ModernUI App, create a new folder called Assets, right click it Add -> New Item... -> ModernUI Theme. Call it whatever you like it.
Inside the newly created XAML file insert these SolidColorBrush under the AccentColor Color tag:
<SolidColorBrush x:Key="SliderSelectionBackground" Color="Red" />
<SolidColorBrush x:Key="SliderSelectionBorder" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBackground" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBackgroundDisabled" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBackgroundDragging" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBackgroundHover" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBorder" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBorderDisabled" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBorderDragging" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBorderHover" Color="Red" />
Each one of these represents a state of the Thumb (the slider "rectangle"). After that open your App.xaml file and include your theme there (this is what my file looks like):
<Application x:Class="ModernUIApp1.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="/FirstFloor.ModernUI;component/Assets/ModernUI.xaml" />
<ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/ModernUI.Light.xaml"/>
<ResourceDictionary Source="/Assets/ModernUI.Theme1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
The <ResourceDictionary Source="/Assets/ModernUI.Theme1.xaml" /> bit represents my theme.
Setting all the colors to Red, this is what it looked like:
I guess that's more clear!
Hope you like it.
EDIT:
It will change when you apply your theme. But, as you're familiar with styles, I'm sending the complete template. What you can do is create a UserDictionary with only this template and when you you want to use it, change the slider Template property. You'll want to change only the Thumb Tags. Pastebin code
And if you want to change only THIS one put the template between <Windows.Resources> or <Slider.Resources> - Another option would be create your own control
I found two approaches:
You can customize your slider by insert corresponding brushes in
appropriate Slider.Resources section.
You can add brushes to separate xaml file with dictionary and then
merge it with corresponding slider in the Slider.Resources. In some cases it fits better because you can change colors of few controls at once.
Any does not need to changing of the control's template.
Both approaches are presented below:
Page1.xaml
<Grid Style="{StaticResource ContentRoot}">
<StackPanel>
<!-- Slider with default theme and colors from ModernUI -->
<Slider/>
<!-- Slider with custom colors from approach 1 -->
<Slider>
<Slider.Resources>
<SolidColorBrush x:Key="SliderSelectionBackground" Color="Green" />
<SolidColorBrush x:Key="SliderSelectionBorder" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBackground" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBackgroundDisabled" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBackgroundDragging" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBackgroundHover" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBorder" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBorderDisabled" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBorderDragging" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBorderHover" Color="Green" />
</Slider.Resources>
</Slider>
<!-- Slider with custom colors from approach 2 -->
<Slider>
<Slider.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Slider.Resources>
</Slider>
</StackPanel>
</Grid>
Dictionary1.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="SliderSelectionBackground" Color="Blue" />
<SolidColorBrush x:Key="SliderSelectionBorder" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBackground" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBackgroundDisabled" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBackgroundDragging" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBackgroundHover" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBorder" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBorderDisabled" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBorderDragging" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBorderHover" Color="Blue" />
</ResourceDictionary>
As result you get following:
Foreground property is used to fill the "completed" part of the slider with a particular color. (Background does the uncompleted part.)
<Slider Value="40" Maximum="100" Foreground="Red" />
Here you have the templates you should use: Slider Styles and Templates
The property you are looking to edit is the TrackBackground.BackGround.
If you define a style for this control template and put it either in you app.xaml or in the window.resources or in any other file, as long as you give it a key you can use it in a specific slider through the "Style" property of that slider using that same key.
Windows 8.1 Store/Phone Apps.
Add this to the App.xaml and change the color values to your liking:
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="SliderTrackDecreaseBackgroundThemeBrush" Color="#FFFF0000" />
<SolidColorBrush x:Key="SliderTrackDecreasePointerOverBackgroundThemeBrush" Color="#FF00FF00" />
<SolidColorBrush x:Key="SliderTrackDecreasePressedBackgroundThemeBrush" Color="#FF0000FF" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrastBlack">
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrastWhite">
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
You probably only want to change the slider for the default theme and probably only the three color values shown above. For all colors / resources that you can change, see this link at MSDN: Slider styles and templates.
For what it's worth, the only way I could change the Slider Thumb color on Win10 UWP for Phone was to overwrite the System Foreground brush. (You can also apparently completely re-template the whole Slider)
So, I put into my 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="Dark">
<Application.Resources>
<SolidColorBrush x:Key="SystemControlForegroundAccentBrush" Color="White" />
</Application.Resources>
</Application>
The addition to Application.Resources is the really important thing here. It's where we're overwriting the Foreground color for ALL common elements, like Checkbox, ContentDialog, ProgressRing, etc.... So, that's the downside to this method too.
Changing the Thumb color on a Slider is a known problem point for XAML UWP. Microsoft has plans to make it easier in the immediate future.
How can I change style of sample MediaElement:
For example how can I change the background.
Code:
<MediaElement AudioCategory="BackgroundCapableMedia" x:Name="media" MediaEnded="Media_MediaEnded" AutoPlay="True" AreTransportControlsEnabled="True" IsMuted="False" Volume="0.5"/>
Actually you can change the colors by overriding the default colors in the App. Note this would apply now for all MediaElement controls with transport controls, but it is possible. In your App.xaml you would provide overrides for these values like this:
<Application.Resources>
<SolidColorBrush x:Key="MediaButtonForegroundThemeBrush" Color="Blue" />
<SolidColorBrush x:Key="MediaButtonBackgroundThemeBrush" Color="Transparent" />
<SolidColorBrush x:Key="MediaButtonPointerOverForegroundThemeBrush" Color="#FFFFFFFF" />
<SolidColorBrush x:Key="MediaButtonPointerOverBackgroundThemeBrush" Color="#26FFFFFF" />
<SolidColorBrush x:Key="MediaButtonPressedForegroundThemeBrush" Color="#FF000000" />
<SolidColorBrush x:Key="MediaButtonPressedBackgroundThemeBrush" Color="#FFFFFFFF" />
<SolidColorBrush x:Key="MediaButtonPressedBorderThemeBrush" Color="#FFFFFFFF" />
<SolidColorBrush x:Key="MediaControlPanelVideoThemeBrush" Color="Red" />
<SolidColorBrush x:Key="MediaControlPanelAudioThemeBrush" Color="#FF000000" />
<SolidColorBrush x:Key="MediaDownloadProgressIndicatorThemeBrush" Color="#38FFFFFF" />
<SolidColorBrush x:Key="MediaErrorBackgroundThemeBrush" Color="#FF000000" />
<SolidColorBrush x:Key="MediaTextThemeBrush" Color="#FFFFFFFF" />
</Application.Resources>
This would give you a visual like this:
Hope this helps!
I think if you do not want to write your own controlpanel with play-pause-stop controls, you can not change the background of this MediaElement rendered controlpanel because it is an overlay of the video and is designed to look MS/Windows8 conform.
Note: This controlpanel is also invisible if you do not mouse-over the video.