I've made a pretty slick Windows 8-ish interface using WPF. It already turns out way better than I could wish for, but I was wondering the following:
Is it somehow possible to retrieve the current window colour set by the user? You know, you can set the Aero colour when you right-click the desktop... My plan is to use that colour for a couple of canvas elements on my GUI.
Thanks in advance!
The SystemColours class exists for this very purpose. You can bind directly to it like so
"{DynamicResource {x:Static SystemColors.WindowColorKey}}"
You can query the ColorizationColor registry key for this.
I've even went a step further and created a method to get the hexadecimal colour value, hope this helps you:
public void SomeMethod()
{
int argbColor = (int)Microsoft.Win32.Registry.GetValue(#"HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM","ColorizationColor", null);
var color = System.Drawing.Color.FromArgb(argbColor);
string hexadecimalColor = ConverterToHex(color);
}
private static String ConverterToHex(System.Drawing.Color c)
{
return String.Format("#{0}{1}{2}", c.R.ToString("X2"), c.G.ToString("X2"), c.B.ToString("X2"));
}
I managed to get the correct colour using the following code:
Little sidenote: It has a small correction in it to ignore the alpha bit of the hex number, so I get the full color rather than the less saturated one.
string colorizationValue = string.Format("{0:x}", Microsoft.Win32.Registry.GetValue(#"HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM", "ColorizationColor", "00000000"));
StringBuilder bl = new StringBuilder(colorizationValue);
bl[0] = 'd';
bl[1] = '9';
colorizationValue = bl.ToString();
BrushConverter bc = new BrushConverter();
Brush brush = (Brush)bc.ConvertFrom("#" + colorizationValue);
cvs_barColor.Background = brush;
I created an open-source library for this here which is also available on NuGet.
install-package aerocolor-wpf.AeroColor
After installing the package, you can refer to a DynamicResource called AeroColor and AeroBrush depending on what you need.
There's some setup code that's needed too, but it isn't much. Just put something in your Loaded event handler of the window, as seen below.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
AeroResourceInitializer.Initialize();
}
}
The neat thing about this library is that it installs a hook as well, which updates those resources as the actual Aero color changes in the system too. This means you don't have to handle that either, and if you use a DynamicResource to point to the color in your XAML instead of a StaticResource, WPF will automatically update the color in your UI as well.
Looks very cool when Windows 8 changes the Aero color transitionally and your color follows.
Related
I wanted to change the disabled background of my Textbox to a semitransparent Gradientbrush (one part transparent the other not).
I found this older post to a almost identical topic: this one
The accepted answer worked for my, as long as I did not wanted to add any transparency to it. Instead the transparent part of the background turns to some shade of gray.
How can I fix this a nice and clean way, the Template form the MS-Page might do the trick, but they always look so awfully giant for such small issues.
I have done something similar to a different control. I added my owncallback to the IsEnabled property like this
static IconPresenter()
{
IconPresenter.IsEnabledProperty.OverrideMetadata(typeof(IconPresenter), new UIPropertyMetadata(new PropertyChangedCallback(OnIsEnabledChanged)));
}
And then I added in the code that I wanted to happen when the IsEnabled is changed
private static void OnIsEnabledChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
IconPresenter iconPresenter = (IconPresenter)sender;
if ((bool)e.NewValue == false)
{
iconPresenter.Fill = Brushes.Transparent;
}
else
{
iconPresenter.Fill = Brushes.Black;
}
}
Im developing an windows phone 8.1 app. I have used shared app bar across the pages. At some point of time, I need to change the label or the icon of the global app bar. Is this possible?
your thoughts will be helpful.
BottomAppBar at WP8.1 is CommandBar, there you will find PrimaryCommands property, in which you probably have AppBarButtons. If you want to change for example a Label (Icon or anything else), you should be able to do it like this:
// change the label of the first button
((BottomAppBar as CommandBar).PrimaryCommands[0] as AppBarButton).Label = "New Label";
If you want to change AppBarButton's parameters often, to make it easier, you can write a simple extension method:
/// <summary>
/// Get AppBarButton of AppBar - extension method
/// </summary>
/// <param name="index">index of target AppBarButton</param>
/// <returns>AppBarButton of desired index</returns>
public static AppBarButton PButton(this AppBar appBar, int index) { return (appBar as CommandBar).PrimaryCommands[index] as AppBarButton; }
Of course it's the same as above, but makes little easier to use:
BottomAppBar.PButton(0).Label = "New label";
If you store your app bar in Resources than you can access it through the following code:
var commandBar = Application.Current.Resources["YouResourceKeyForAppBar"] as AppBar;
Now you have a reference to it and you can modify items inside it. If you implemented SharedApp in another way, please edit your question and tell more information about it.
Perhaps I can suggest an alternate solution thanks to the 8.1 libraries in the Windows.UI.ViewManagement namespace namely the StatusBar and the ApplicationView's Title
It won't help out this situation, but might make things simpler for another who is looking at this post.
var titleName = "TITLE";
var statusBar = Windows.UI.ViewManagement.StatusBar.GetForCurrentView();
statusBar.ProgressIndicator.Text = titleName;
var applicationView = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView();
applicationView.Title = titleName;
Then to show and hide, control with:
await statusBar.ProgressIndicator.ShowAsync();
await statusBar.ProgressIndicator.HideAsync();
Unfortunately, the only thing you'll be able to set up here is Title. I don't think you can set a custom Style to the StatusBar.
public MainPage()
{
this.InitializeComponent();
Loaded += MainPage_Loaded;
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
CommandBar bottomCommandBar = this.BottomAppBar as CommandBar;
AppBarButton appbarButton_0 = bottomCommandBar.PrimaryCommands[0] as AppBarButton;
appbarButton_0.Label = "settings";
appbarButton_0.Icon = new SymbolIcon(Symbol.Setting);
}
I've been working on developing a custom control which will be used in our CRM frontend. The control itself is nothing special, it simply wraps two labels, text edits, and a button into a single control. (The control is only acting as a wrapper, a bit long winded, but unfortunately our only option due to various restrictions)
I though it would be nice to give the control a Font and ForeColor property, that would change the Font and Color of the labels. Changing the font size means that the relative position of the text boxes be changed to keep everything in line. No problem.
I encapsulated the layout logic in an UpdateLayout method, which is called on the set accessor of the Font property and everything works beautifully at design time, however, at runtime, the Font of the labels is correct, but the layout of the text boxes and button are still in the default positions, hence, the labels overlap.
What am I missing in for updating the position of controls at the init stage in runtime? I've tried calling the UpdateLayout() method from both Initialize and the constructor of the control, alas to no avail.
Am i missing something obvious here?
EDIT:
As requested, I whipped up a quick test. My test control looks like so (Not including Designer code):
public partial class TestControl : UserControl
{
private Font _font;
[Browsable(true)]
public override Font Font
{
get
{
return this._font ?? SystemFonts.DefaultFont;
}
set
{
this._font = value;
this.DoLayout();
}
}
private void DoLayout()
{
this.label1.Font = this._font;
this.Size = new Size(label1.Width + textBox1.Width + 10,
label1.Height >= textBox1.Height ? label1.Height : textBox1.Height);
this.textBox1.Location = new Point(label1.Location.X + 5 + label1.Width, 1);
this.Update();
}
public TestControl()
{
InitializeComponent();
}
protected override void OnLayout(LayoutEventArgs e)
{
base.OnLayout(e);
DoLayout();
}
}
That works great at design time, but runtime, less so...
EDIT2:
So the above code doesn't entirely reflect the problem accurately, however, I have tried Jogy's suggestion of overriding the OnLayout method, and lo and behold, it works!
I'm relatively new to Custom Controls, so a rookie mistake on my part. This will definitely be committed to the long term memory.
Override OnLayout() method and call your UpdateLayout() there.
Thanks for supplying the code, I would provide the properties by reusing already available controls.
public override Font Font
{
get { return this.label1.Font; }
set
{
this.label1.Font = value;
// Additional code to update related controls.
}
}
Also be aware that the declaration of
private Font _font;
Delivers a non-initialized variable, and by using it in the "Do_Layout" might use a null value. Maybe change it to the following when using your code.
this.label1.Font = this.Font;
I have the following code:
[OnTap ("Account")]
[Alignment (UITextAlignment.Center)]
[Entry ("Create ScanDo! Account")]
public string Login;
And I'd like to set the Cell background color dynamically, based on the contents of another field and then after the button is clicked. Could anyone point me in a direction with some samples?
Thanks,
Rick
The answer I came up with:
btnLogin = new StyledStringElement("", delegate {Account();})
To define the object, add it to the RootElement, then:
btnLogin.BackgroundColor = UIColor.Green;
To set the color! This method let me set color, font, size and caption.
Great work Miguel, Thanks!
As you're adding the button to the root collection you can set the colour. Just as you set the elements of a section.
Root = new RootElement("First Section") {
new Section ("Test"){
new StyledStringElement("Login", delegate { Account(); })
{
BackgroundColor = UIColor.Green
}
}
}
I don't like to keep pimping my projects but in this case it is the best option for you.
Check out https://github.com/RobertKozak/MonoMobile.MVVM
My project started out as adding Databinding support to MonoTouch.Dialog but has grown into a much bigger framework that is much easier to use than MonoTouch.Dialog.
Using MonoMobile.MVVM the code to do what you want looks like this:
public class ButtonView : View, INotifyPropertyChanged
{
private UIColor ButtonColor = UIColor.Red;
[Button]
[Bind("ButtonColor", "BackgroundColor")]
public void Test()
{
ButtonColor = UIColor.Green;
PropertyChanged(this, new PropertyChangedEventArgs("ButtonColor"));
}
public event PropertyChangedEventHandler PropertyChanged = (s,e)=>{};
}
There are better ways to accomplish this using a proper ViewModel but this will work as listed (I tested it before I typed it in here.)
MonoMobile.MVVM is still in beta but there is enough there to get you going. It should be in full release status in the next couple of weeks after I finish up implementing INotifyCollectionChanged and adding a few more bindings for various Element properties.
I've got a StatusStrip with a single ToolStripStatusLabel, Spring=true and a background color for notifications.
The problem is that there's an ugly gray square on the right side of the status strip. After fiddling for a while, I realized this is the sizing grip (I had is set to SizingGrip=false, GripStyle=Hidden). Yet even with it hidden, it still hogs the space. I can't get any content on the status strip to extend all the way to the right.
How would you work around this? Note I can't just set the backcolor of the StatusStrip because the Status Label changes colors and has some fading effects.
The StatusStrip.Padding property is borked, it returns the wrong value for Padding.Right if the sizing grip is disabled. You can fix it in your form constructor, like this:
public Form1() {
InitializeComponent();
statusStrip1.Padding = new Padding(statusStrip1.Padding.Left,
statusStrip1.Padding.Top, statusStrip1.Padding.Left, statusStrip1.Padding.Bottom);
}
Using the Left property to specify Right is the fix. Don't bother submitting this bug to Connect, they won't fix it.
Have a look at this blog entry on MSDN. The question was about changing the size of the sizing grip manually, and I think using the ToolStrip Renderer as suggested could work for you also.
The problem I have so far, is that it removes the background color on a status label in the StatusStrip, so it's not a solution yet, but it's a start.
public MyForm()
{
InitializeComponent();
statusStrip1.Renderer = new MyRenderer();
}
private class MyRenderer : ToolStripProfessionalRenderer
{
protected override void OnRenderStatusStripSizingGrip(ToolStripRenderEventArgs e)
{
// don't draw at all
}
}
I had following problem: when I set tsslSeparator.Spring = true, my right label disappeared immediately after tsslSeparator lost focus. The issue appeared when sizing grip was enabled. When it was disabled, everything worked just fine.
The solution was to set right margin for right label to something different than 0.
tsslLogging.Margin = new Padding(0, 3, 2, 2); // this is necessary for right alignment of status bar label
Hope this helps somebody.
If Microsoft isn't interesting in fixing it, it seems like a proper fix should handle all orientations, and ideally fix all Status Strips (see my answer to Get All Children for definition of GetAllChildren)
public static StatusStrip FixPadding(this StatusStrip ss) {
if (!ss.SizingGrip) {
var fixpad = ss.Padding;
if (ss.Orientation == Orientation.Horizontal) {
if (ss.RightToLeft == RightToLeft.No)
fixpad.Right = fixpad.Left;
else
fixpad.Left = fixpad.Right;
}
else
fixpad.Bottom = fixpad.Top;
ss.Padding = fixpad;
}
return ss;
}
public static void FixStatusStripPadding(this Form f) {
foreach (var ss in f.GetAllChildren().OfType<StatusStrip>())
ss.FixPadding();
}