Styling Ribbon from the RibbonControlsLibrary - wpf

Ribbon is nice. I want to make it nicer... (IMHO)
With the Ribbon (from RibbonControlsLibrary on .NET 3.5 sp1), it is ok to change some backgrounds and foregrounds. But the thing I want to re-style is the white "mask" (linear gradient brush with alpha) that seats in the "background" of the RibbonTabGroup. I saw it with Snoop. I found it in the style.
<LinearGradientBrush x:Key="[49] Í" StartPoint="0.5,0.0" EndPoint="0.5,1.0">
<GradientStop Color="#EEFFFFFF" Offset="0.0" />
<GradientStop Color="#BBFFFFFF" Offset="0.1" />
<GradientStop Color="#05FFFFFF" Offset="0.5" />
<GradientStop Color="#20FFFFFF" Offset="1.0" />
</LinearGradientBrush>
But still I have no idea how to override it. I don't know either where it is set...
Cheers, Patrick

I got it!
With help of the following post Serialize a UserControl to xaml, but not its children? [Many thanks to you Will]. I could extract the "default" style. So I obtain the complete style. What I did before, open RibbonControlsLibrary with .NET Reflector and read the XAML with BAML Viewer. Not ideal in my case.
Just in case someone has the same wish, obtaining the default style of component (when it isn't published #MSDN):
System.Windows.Style style = Application.Current.FindResource(typeof(Microsoft.Windows.Controls.Ribbon.Ribbon)) as System.Windows.Style;
var sb = new System.Text.StringBuilder();
var writer = System.Xml.XmlWriter.Create(sb, new System.Xml.XmlWriterSettings
{
Indent = true,
ConformanceLevel = System.Xml.ConformanceLevel.Fragment,
OmitXmlDeclaration = true
});
var mgr = new System.Windows.Markup.XamlDesignerSerializationManager(writer);
mgr.XamlWriterMode = System.Windows.Markup.XamlWriterMode.Expression;
System.Windows.Markup.XamlWriter.Save(style, mgr);
string styleString = sb.ToString();
Cheers, Patrick

Related

Silverlight: change property of drawn object. -- should be easy & how to debug code

Say I have a rectangle in silverlight that I created in Blend. How can I change the background fill on the object.
XAML
<Rectangle x:Name="Background" Stroke="Black" StrokeThickness="0" Height="480" Width="640">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
<GradientStop Color="#FED40707" Offset="0.164"/>
<GradientStop Color="#FED5EB0E" Offset="0.392"/>
<GradientStop Color="#FE849AF4" Offset="0.595"/>
<GradientStop Color="#FE2C9937" Offset="0.797"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
.cs file
Rectangle Background = new Rectangle();
string fileName = "Images/yello.png";
BitmapImage image = new BitmapImage(new Uri(fileName, UriKind.Relative));
ImageBrush brush = new ImageBrush();
brush.ImageSource = image;
Background.Fill = brush;
Background.UpdateLayout();
This runs but nothing happens. Also how can I debug this code. I loaded the project file into VS 2012 but when it runs it won't stop on breakpoints.
Also tried:
Background.Fill = new SolidColorBrush(Colors.Red);
Your .cs code fails as you are newing a rectangle called Background, that has nothing to do with the element named Background in your XAML file.
When you name an element in a XAML file, a C# member of that name is generated in the designer file and that property is connected to the XAML element (via a search by name of the loaded XAML element tree). That means that all named elements can simply be referenced as properties in the code behind. Take a look in your designer file to get a feel for what is going on behind the scenes.
Remove the Rectangle Background = new Rectangle(); line and try again. You also should not need to call Background.UpdateLayout();
You also probably want to choose another name, rather than Background, for your rectangle element as that may cause confusion with the Background property of all Panel elements
There may be other problems, but best you sort out these ones first :)

Giving a stackPanel the same LinearGradientBrush as the toolbar has by default

I have two ToolBars side by side (I had to do that so I could align buttons right and left)
But now, I have to add some text that can be aligned right left or center between both toolbars. I added the text in a TextBlock inside a StackPanel disposed on a Grid at the second position (between the toolbars) and, of course, it created a gap between both toolbars (A stackPanel doesn't have the same style as a toolbar, of course).
I would like to replicate the toolbar LinearGradientBrush on my stackpanel so it looks the same as my toolbar does. the point is to make the thing look like ONE toolbar.
Is there a way to get the ToolBar Style or to recreate it with a LinearGradientBrush definition, and if so, how?
Here's one way you could do it. Say one of your toolbars' name is "toolBar." Bind the Background property on the StackPanel to the Background property on the ToolBar as such:
<StackPanel Background="{Binding Path=Background, ElementName=toolBar}" />
Hope that helps! :)
EDIT:
You can check out the control template for the ToolBar here.
The LinearGradientBrush used looks as such:
<LinearGradientBrush x:Key="DarkBrush" StartPoint="0,0" EndPoint="0,1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#FFF" Offset="0.0"/>
<GradientStop Color="#AAA" Offset="1.0"/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
In the event you just wanted to use this instead of binding. :)
The default templates and styles are available on MSDN, you could probably extract the relevant bits from there.
I found an issue when doing this exact same thing in an application. When running the same application on an XP machine as I did a Vista machine, I found that there was a 2 pixel difference in the height between the two toolbars.
To get around this, I ended up creating one StackPanel which housed the two tool bar objects (setting the background to be transparent).
This ensured that the look and feel was the same between the two OS's (at the time the company was running both) and will also aid you in the event that one of your toolbars grow in height without the other.

WPF 3D - mapping gradient brush on complex geometry

I wanted to ask if anyone knows how to map gradient brush on complex objects in WPF 3D. The result should look similar to 3D images in matlab (3D function for example). Lets say you have some 3-dimensional data you wish to visualize and you want to diferentiate certain levels of values by color.
Given a GradientBrush defined something like this:
<LinearGradientBrush x:Name="RedYellowGradient">
<GradientStop Color="Blue" Offset="0.01" />
<GradientStop Color="Purple" Offset="0.25"/>
<GradientStop Color="Red" Offset="0.5"/>
<GradientStop Color="Orange" Offset="0.75"/>
<GradientStop Color="Yellow" Offset="1.0"/>
</LinearGradientBrush>
Fundamentally, you assign the GradientBrush to the DiffuseMaterial of your MeshGeometry3D. When defining the brush, set its ViewportUnits property to "Absolute".
Something like this would work directly in the code-behind of a XAML form (otherwise, create the brush in code (in your ViewModel) using the corresponding properties, or call it from your resource dictionary):
MyMaterial = New DiffuseMaterial(RedYellowGradient) With {.ViewportUnits = BrushMappingMode.Absolute}
Then, for each Point3D in your geometry, assign a value between 0.0 and 1.0 to the corresponding texture coordinate. Generically, for a pre-sized Point array it could look like this:
Parallel.For(0, positions.Count - 3, Sub(i)
Dim p = positions(i)
Dim plotValue = GetYourValue(p.X, p.Y, p.Z)
Dim t = (plotValue - minPlot) / (maxPlot - minPlot)
If t < 0 Then t = 0
If t > 1 Then t = 1
arr(i) = New Point(t, 0.5)
End Sub)
If your facets are very long or the values between vertices very far apart, your plotting will look odd. But given the strictures of WPF 3D it's probably the best you can do without a lot of UV Mapping.
(If you need C#, the Roslyn CTP has a VS Add-on which will convert VB code on the clipboard to C#...)

How to create a repeating background with xaml elements in silverlight?

I want to create an area in my application that looks draggable. Usually, you see this done with a background of small dots or squares, or sometimes lines. I'm using Silverlight and I want to simply create a background that is a set of repeating small rectangles. I honestly cannot figure out how to generate a background with xaml. I'd rather not have to create every little rectangle -- this will also cause the control not to scale. Is there some way to repeat xaml elements to form a pattern? This would be similar to CSS repeating backgrounds, but I would like to use xaml instead of images.
You can use a brush, like this:
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush EndPoint="6,6" StartPoint="2,2" SpreadMethod="Repeat" MappingMode="Absolute">
<GradientStop Color="#FFAFAFAF" Offset="0"/>
<GradientStop Color="#00FFFFFF" Offset="1"/>
<GradientStop Color="#00FFFFFF" Offset="0.339"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
I've nicked this particular example from the excellent blacklight project, you'll need to play around with all the different settings to see what does what. I'm guessing a radial brush will allow you to get dots, etc. I think they created it in blend as all the numbers were crazy decimals until I sanitised them a bit.

WPF: Changing Resources (colors) from the App.xaml during runtime

I am trying to make my application more customizable by allowing users to pick a color from a Color Picker dialog, and then changing the style of the application in real time (with DynamicResource)
How do I go about in changing specific resources that reside in the app.xaml ?
I have tried something like this but no luck (just a test):
var colorDialog = new CustomControls.ColorPickerDialog();
var dResult = colorDialog.ShowDialog();
var x = Application.Current.Resources.Values.OfType<LinearGradientBrush>().First();
x = new LinearGradientBrush();
x.GradientStops.Add(new GradientStop(colorDialog.SelectedColor,1));
This an excerpt of the app.xaml file:
<Application.Resources>
<LinearGradientBrush x:Key="HeaderBackground" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#82cb02" Offset="1"/>
<GradientStop Color="#82cb01" Offset="0.2"/>
<GradientStop Color="#629a01" Offset="0.5"/>
</LinearGradientBrush>
</Application.Resources>
What is the best way to allow this form of customizability (basically just changing some colors) to an application?
[Update]
I just found this answer from a previous question that was asked, and tried it but I am getting the same InvalidOperationException exception Petoj mentioned in the comments for the given answer. Here is the sample code from the answer:
Xaml:
<LinearGradientBrush x:Key="MainBrush" StartPoint="0,0.5" EndPoint="1,0.5" >
<GradientBrush.GradientStops>
<GradientStop Color="Blue" Offset="0" />
<GradientStop Color="Black" Offset="1" />
</GradientBrush.GradientStops>
</LinearGradientBrush>
C#:
LinearGradientBrush myBrush = FindResource("MainBrush") as LinearGradientBrush;
myBrush.GradientStops[0].Color = Colors.Red;
It looks like you're trying to do some sort of skinning?
I'd recommend defining the resources in a Resource Dictionary contained in a separate file. Then in code (App.cs to load a default, then elsewhere to change) you can load the resources as so:
//using System.Windows
ResourceDictionary dict = new ResourceDictionary();
dict.Source = new Uri("MyResourceDictionary.xaml", UriKind.Relative);
Application.Current.Resources.MergedDictionaries.Add(dict);
You could also define the default resource dictionary in App.xaml and unload it in code just fine.
Use the MergedDictionaries object to change the dictionary you're using at runtime. Works like a charm for changing an entire interface quickly.
Changing application wide resources in runtime is like:
Application.Current.Resources("MainBackgroundBrush") = Brsh
About the InvalidOperationException, i guess WallStreet Programmer is right.
Maybe you should not try to modify an existing brush, but instead create a new brush in code with all the gradientstops you need, and then assign this new brush in application resources.
Another Approach on changing the color of some GradientStops is to define those colors as DynamicResource references to Application Wide SolidColorBrushes like:
<LinearGradientBrush x:Key="MainBrush" StartPoint="0, 0.5" EndPoint="1, 0.5" >
<GradientBrush.GradientStops>
<GradientStop Color="{DynamicResource FirstColor}" Offset="0" />
<GradientStop Color="{DynamicResource SecondColor}" Offset="1" />
</GradientBrush.GradientStops>
and then use
Application.Current.Resources["FirstColor"] = NewFirstColorBrsh
Application.Current.Resources["SecondColor"] = NewSecondColorBrsh
HTH
Use the Clone() method to make a deep copy of the brush (or any other freezable object like Storyboard) and then use it:
LinearGradientBrush myBrush = FindResource("MainBrush") as LinearGradientBrush;
myBrush = myBrush.Clone();
myBrush.GradientStops[0].Color = Colors.Red;
#WallstreetProgrammer is right - all application level resources are frozen by default.
Thats why you need to clone the object first.
You get an exception because you are trying to modify a frozen object. All application level resources are automatically frozen if they are freezable and LinearGradientBrush is. If you add it on a lower level like window level it will work.

Resources