I have a simple WPF Application to change color themes.
ResourceDictionary blueDict = new ResourceDictionary() { Source = new Uri(#"/Styles/Colors/Blue/BlueColors.xaml", UriKind.Relative) };
ResourceDictionary greenDict = new ResourceDictionary() { Source = new Uri(#"/Styles/Colors/Green/GreenColors.xaml", UriKind.Relative) };
ResourceDictionary yellowDict = new ResourceDictionary() { Source = new Uri(#"/Styles/Colors/Yellow/YellowColors.xaml", UriKind.Relative) };
ResourceDictionary genericDict = new ResourceDictionary() { Source = new Uri(#"/Styles/Colors/GenericColors.xaml", UriKind.Relative) };
On the MainWindow I have a ComboBox that stores three enum values "Blue, Green, Yellow". That's what it does when the selected index has changed:
Application.Current.Resources.MergedDictionaries.Clear();
Themes newTheme = (Themes)cbxThemes.SelectedItem;
if (newTheme == currentTheme)
return;
switch (newTheme)
{
case Themes.Blue:
Application.Current.Resources.MergedDictionaries.Add(blueDict);
break;
case Themes.Green:
Application.Current.Resources.MergedDictionaries.Add(greenDict);
break;
case Themes.Yellow:
Application.Current.Resources.MergedDictionaries.Add(yellowDict);
break;
default:
break;
}
Application.Current.Resources.MergedDictionaries.Add(genericDict);
currentTheme = newTheme;
The first time, everything works well and I can choose whatever color I want, but when I change Colors again, nothing happens.
Is there anything that doesn't update in the background?
The code works, if you output the Application.Current.Resources.MergedDictionaries you can even see the new source. Only the UI is not updated.
I found a solution:
Simply replace
Application.Current.Resources.MergedDictionaries.Add(yourDictionary);
with
Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri(#"yourPath.xaml", UriKind.Relative) });
As often in programming I have no idea why it works but first of all I'm happy. If someone could explain this to me, that'd be great.
Try replacing this line:
Themes newTheme = (Themes)cbxThemes.SelectedItem;
with this line:
string newTheme = ((ComboBoxItem)cbxThemes.SelectedItem).Content.ToString();
Ofcourse you'd also need to change how you handle the comparison between newTheme and currentTheme.
If you don't want to use a string, you can convert it to enum by using:
Themes newTheme;
Enum.TryParse(((ComboBoxItem)cbxThemes.SelectedItem).Content.ToString(), out newTheme);
Related
I would like to give the user an option to change the theme from dark to light, by clicking the button.
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyApp"
x:Class="CoreBackup.App">
<Application.DataTemplates>
<local:ViewLocator/>
</Application.DataTemplates>
<Application.Styles>
<StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/>
<StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseDark.xaml"/>
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Default.xaml"/>
</Application.Styles>
How I can get access from other ViewModel to the Application.Styles?
I don't know if the problem is solved. So may be this helps to switch the theme from BaseDark to BaseLight.
private void ChangeLayoutExecute(object o)
{
// create new style
var newStyle = new StyleInclude(new Uri("avares://AvaloniaApplicationTest/App.xaml"));
newStyle.Source = new Uri("avares://Avalonia.Themes.Default/Accents/BaseLight.xaml");
// load style to get access to the ressources
var baseDarkStyle = newStyle.Loaded as Style;
// get the original source (BaseDark)
var ressourceFromAppXaml = ((Style)((StyleInclude)Application.Current.Styles[1]).Loaded).Resources;
foreach (var item in baseDarkStyle.Resources)
{
// for secure lookup if the key exists for the resource otherwise create it
if (ressourceFromAppXaml.ContainsKey(item.Key))
ressourceFromAppXaml[item.Key] = item.Value;
else
ressourceFromAppXaml.Add(item.Key, item.Value);
}
// set source name for the new theme
((StyleInclude)Application.Current.Styles[1]).Source = new Uri("avares://Avalonia.Themes.Default/Accents/BaseLight.xaml");
}
how do i set a buttons name when i created it in c# so i can call it later?
i have a a List of strings (Commands).
i loop over it an create a button for each item in the List.
commands.ForEach(delegate (String i)
{
Button button = new Button()
{
Name = i,
Tag = i,
MaxWidth = 50,
MaxHeight = 50,
BorderBrush = null
};
button.Click += new RoutedEventHandler(button_Click);
this.grid.Children.Add(button);
Uri resourceUri = new Uri("led_Off.png", UriKind.Relative);
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
var brush = new ImageBrush();
brush.ImageSource = temp;
button.Background = brush;
});
This loop works fine until i add the line
Name = i
i am in a spot where these buttons were created and i now need to change some of there back ground images.
is there a better way to call them then by there name?
Name should be a valid string: try Name = "button" + i.ToString() (FYI, Button Name cannot be just "1", it's an invalid Name). Also, Tag =i.ToString(). Hope this may help
Don't do it, use data binding and data templating with commands instead.
There is no reason to ever create any UI elements in a loop in WPF.
Edit: Just this.
How to add a parameter for an image to this variable?
var selectionDisplay = new SelectionDisplay(button.Label as string);
Thanks in advance!
EDIT:
I have this set of images and their respective code below (see pic1)
This is where the program gets the images to be displayed. The code for the buttons is this one:
var files = Directory.GetFiles(#".\GalleryImages");
foreach (var file in files)
{
FileInfo fileInfo = new FileInfo(file);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(file, UriKind.Relative);
bi.EndInit();
var button = new KinectTileButton
{
Label = System.IO.Path.GetFileNameWithoutExtension(file),
Background = new ImageBrush(bi)
};
this.wrapPanel.Children.Add(button);
}
This is where the program gets the images to be displayed.
The code for the buttons is this one:
private void KinectTileButtonclick(object sender, RoutedEventArgs e)
{
var button = (KinectTileButton)e.fake_fake_fakeource;
var selectionDisplay = new SelectionDisplay(button.Label as string);
this.kinectRegionGrid.Children.Add(selectionDisplay);
e.Handled = true;
Right now, when i click on of the images, the SelectionDisplay window pops up, which look like this (see pic2). What i want is that when I click an image the SelectionDisplay window should open with the respective image... meaning that if I click on the image with a dog, the window should open with the dog's image, not with other image.
I hope I've made myself clear and that you can help me.
http://i58.tinypic.com/8zl6h3.jpg
http://i57.tinypic.com/208fosy.png
is this the constructor you are talking about? is this where i should make changes? should i add something after "string itemid"?
public SelectionDisplay(string itemId)
{
this.InitializeComponent();
this.messageTextBlock.Text = string.Format(CultureInfo.CurrentCulture,Properties.Resources.SelectedMessage,itemId);
}
I see two approaches:
Just pass the image brush in your constructor. Its view->view, so you aren't breaking MVVM (and it looks like you aren't using that pattern anyways).
new SelectionDisplay(button.Label, button.Background);
Set the path as the "tag" of the button. The tag property is an object you can put whatever you want into (the framework does not use it, and so it is included for this very purpose). Then just pass the string to SelectionDisplay, and instantiate the image just like you are doing for the button:
var button = new KinectTileButton
{
Label = System.IO.Path.GetFileNameWithoutExtension(file),
Background = new ImageBrush(bi),
Tag = file
};
var selectionDisplay = new SelectionDisplay(button.Label as string, button.Tag as string);
FrameworkElement.Tag on MSDN (Note that Button derives from FrameworkElement, as do all controls, so it automatically has it as well!)
UPDATE
I see that SelectionDisplay is a UserControl in your project, so you just need to change its constructor to look like:
Numbers match above:
SelectionDisplay(string labelText, ImageBrush sourceImage)
SelectionDisplay(string labelText, string imagePath)
That is the source of the error you are getting, you have to modify the constructor to take the new parameter.
Please let me know if I can clarify anything.
Can anyone help me to Change background color of all text boxes in single click function in Windows Phone 8. In a form I have more then 50 text boxes. I can code like
textbox.BorderBrush = new SolidColorBrush(Windows.UI.Colors.Red);
textbox1.Background = new SolidColorBrush(Colors.Red);
textbox2.Background = new SolidColorBrush(Colors.Red);
textbox3.Background = new SolidColorBrush(Colors.Red);
textbox4.Background = new SolidColorBrush(Colors.Red);
textbox5.Background = new SolidColorBrush(Colors.Red);
up to
textbox50.Background = new SolidColorBrush(Colors.Red);
But I need an effective way.
There are as usual ore ways to do it. Suppose all the TextBoxes are childres of some cotainer like a StackPanel or Grid. The simplest way would be to iterate the containers Children:
foreach (var elem in container.Children)
{
if (elem is TextBox)
{
(elem as TextBox).Background = new SolidColorBrush(Colors.Red);
}
}
A better way in my opionion would be using MVVM and bind the Background property to some property in your ViewModel. If you change the property to Red, all the TextBoxes will automaticaly register the change
I have been trying to create a ContentTemplate using the lovely Frameworkelementfactory.
The code works except I can't set the content of the Button. I have tried many things but I always end up with a Button with Content= Button.
Here is the code which generates the contenttemplate. For your further info, I am using this in a Tabcontrol Header Itemtemplate...
Cheers.
ControlTemplate ct = new ControlTemplate(typeof(TabItem));
FrameworkElementFactory spouter = new FrameworkElementFactory(typeof (DockPanel));
FrameworkElementFactory text = new FrameworkElementFactory(typeof(TextBlock));
text.SetValue(TextBlock.TextProperty, Name);
spouter.AppendChild(text);
FrameworkElementFactory mButtonPrev = new FrameworkElementFactory(typeof(Button));
mButtonPrev.SetValue(System.Windows.Controls.Button.ContentProperty, "x");
mButtonPrev.AddHandler(System.Windows.Controls.Button.ClickEvent, new RoutedEventHandler(CloseTab));
spouter.AppendChild(mButtonPrev);
ct.VisualTree = spouter;
return ct;
ControlTemplate ct = new ControlTemplate(typeof(TabItem));
Shouldn't you be creating a DataTemplate here instead?
(Everything else looks fine to me, also FEF is deprecated, read the docs)
For those of use still using FEF, I was able to set the content of my button with the actual string. I see Name as where "button" is coming from in your example. In my example, Name pulls up the class name that I'm binding to my datagrid.
var buttonTemplate = new FrameworkElementFactory(typeof(Button));
var text = new FrameworkElementFactory(typeof(TextBlock));
text.SetValue(TextBlock.TextProperty, "Save");
buttonTemplate.AppendChild(text);
buttonTemplate.AddHandler(
System.Windows.Controls.Primitives.ButtonBase.ClickEvent,
new RoutedEventHandler((o, e) => MessageBox.Show("hi"))
);
AccountDatagrid.Columns.Add(new DataGridTemplateColumn()
{
Header = "Save",
CellTemplate = new DataTemplate() { VisualTree = buttonTemplate }
});
AccountDatagrid.ItemsSource = AccoutDescCodeTime.GetBaseAccounts();