I'm trying to override the padding property of a ListViewItemPresenter in Windows Store apps.
Everything works when I copy the complete generic ListView style, change the padding and apply that style as ItemContainerStyle to my ListView.
Now I need to do this for another ListView. How can I override just one property of the ListViewItemPresenter ControlTemplate without copying the complete style all over again?
The best solution I have found came from the link below. I copy-pasted the answer below.
The idea is to copy the full Windows 10 style into your dictionary and give it a key. You don't need to modify the style and you only have to copy it once. (Though once more than ideally you should have to.) Since it now has a key, you can create another style "BasedOn" that key and modify it.
[https://social.msdn.microsoft.com/Forums/en-US/d3c1f120-b11f-4d14-b45c-7bdf3e9233be/inheriting-a-default-application-style-xaml?forum=winappswithcsharp][1]
First, create the default style for the control in your App.xaml-level resource dictionary, but give it an x:Key
<Style x:Key="ButtonDefaultStyle" TargetType="Button">
...
</Style>
Then, create another style that inherits from this style.
<Style x:Key="MyButtonStyle" TargetType="Button" BasedOn="{StaticResource ButtonDefaultStyle}" />
</Style>
Default styles can be found here
[https://msdn.microsoft.com/en-us/library/windows/apps/mt299122.aspx]
or on your computer at a location like
C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.10586.0\Generic\generic.xaml
Related
I recently switched to Visual Studio 2017, and my xaml design time view has suffered considerably.
The most recent challenge is a design time-only bug where my components won't show up because their style_1093579 doesn't match style_0965327, but when I run the program, it works fine.
I agree that the numbers don't match, but I didn't add them, and can't figure out how to update them. I have tried cleaning, resetting, reverting, and manually deleting files. I've attached to the process to try to debug it. I've added [DesignTimeVisible(true)] to see if that would change anything - all I've managed to do is get some of the numbers to change. I've Googled, but even the promising questions, like TargetType does not match type of Element or 'Chart' TargetType does not match type of element 'Chart' either don't apply, or are not answered.
My best guess is that some auto generated file does not get regenerated correctly when I rebuild. (it's not the *.g.i.cs file though - I already tried deleting it.) Does anyone have another file I should try deleting, or a workaround?
I had a similar problem when creating a view based on my custom ContentControl, where I had created a Style for my custom ContentControl.
Try to explicitly set the TargetType of the Style on the CustomButton to the one used on the element that the Style is defined with.
So in in a view that is based on your CustomButton
<my:CustomButton x:Class="MyModule.Views.MyButtonView">
<my:CustomButton.Style>
<Style BasedOn="{StaticResource StyleCustomButton}" TargetType="{x:Type my:CustomButton}" />
</my:CustomButton.Style>
</my:CustomButton>
when StyleCustomButton is defined similar to this:
<Style x:Key="StyleCustomButton"
TargetType="{x:Type my:CustomButton}">
...
I have a Style with target type Grid. I want all Entry child elements within a grid of this style to automatically acquire a particular style.
I've had a look at these:
Styling nested elements in WPF
Apply Style to all child-elements of specific type
The only solution appears to be setting Resources within the parent Style, so this is what I've done:
<Style x:Key="BuggyGrid" TargetType="Grid">
<!-- bunch of property setters -->
<Style.Resources>
<Style TargetType="Entry">
<Setter Property="FontFamily" Value="Arial" />
</Style>
</Style.Resources>
</Style>
However, I get a build error:
"No property, bindable property, or event found for 'Resources'".
Why do I get this error?
I'm using Xamarin.Forms 2.3.2.
The links you have referenced are specific to WPF XAML and do not apply to Xamarin.Forms XAML.
I'm not sure how you would achieve nested styles in Xamarin.Forms.
The only possibility is XamlCSS which I haven't personally used.
https://www.nuget.org/packages/XamlCSS.xamarinforms/2.0.0-pre1
The official Microsoft article states:
Modify the default system styles
You should use the styles that come from the Windows Runtime default XAML resources when you can. When you have to define your own styles, try to base your styles on the default ones when possible (using based-on styles as explained earlier, or start by editing a copy of the original default style).
I understand that you can copy and paste the default style from MSDN in order to "start by editing a copy of the original". However, that strikes me as very ugly and inelegant, as I'm pasting in almost a 100 lines even if I just want to add one thing.
I like the idea of "using based-on styles" to include all of the default style by reference, but from what I can tell the original default styles supplied by Microsoft are implicit. Given that they have no key to reference them by, how can BasedOn be used?
You are right about that BasedOn won't work with default styles as they are implicit.
However, you don't have to include the full style code if you simply want to edit some properties.
For example, the Button below will inherit everything from the default style except the Background color being changed to Red.
<Page.Resources>
<Style x:Key="RedButtonStyle"
TargetType="Button">
<Setter Property="Background"
Value="Red" />
</Style>
</Page.Resources>
<Grid>
<Button Content="Red" Style="{StaticResource RedButtonStyle}" />
</Grid>
I want to make ComboBoxes in my Windows 10 App to have theme colours (One have a green theme, one with an orange theme...etc). I can do it by making different styles for each different colour, but that adds a huge amount of markup and it's a mess to manage. Because they're also the styles, I read that bindings won't work because styles are sealed once they're initialized.
Has anyone figured out a way to just change colours of a style without having to make multiple separate styles?
WPF has some nice markup for this very problem. You can use DynamicResource to allow the style to refresh every time the resource gets changed. Here's an example:
<SolidColorBrush x:Key="ColourAccent">#448AFF</SolidColorBrush>
<Style TargetType="Button">
<Setter Property="Background" Value="{DynamicResource ColourAccent}"/>
</Style>
This of course is a very simple implementation of this method, but essentially the DynamicResource is a reference to ColourAccent that, if the resource was to change, will automatically reflect the change in the style.
Now, changing the resource is a slightly different problem, for theming your styles, you need somewhere to put all of your colours, the solution here is to use multiple ResourceDictionaries and using MergedDictionaries. Let me show you what I mean:
Firstly, add a folder to your project called Themes, it'll just make things easier. Also, add that Style I mentioned earlier to either the Window.Resources or App.Resources, it's pretty important.
You need to add a ResourceDictionary file to the folder (Call it Amber.xaml), it'll look something like this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Amber -->
<SolidColorBrush x:Key="ColourAccent">#FFC107</SolidColorBrush>
</ResourceDictionary>
Here is a simple resource dictionary, it contains one resource called ColourAccent, now we need to create another one (Call it Blue.xaml), but with a different colour:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Blue -->
<SolidColorBrush x:Key="ColourAccent">#448AFF</SolidColorBrush>
</ResourceDictionary>
The magic here will become clear soon enough. Having multiple resource dictionaries with resources under the same name will allow you to create themes. The method of which is to swap the current resource dictionary for a new one, and by doing so, the DynamicResource will notice there has been a change and it'll refresh the control styles.
Now you have two resource dictionaries, you need to work out which dictionary to use. Firstly, we need to define the default resource dictionary that your application is going to use, you need to declare this in App.xaml.
<Application ...>
<Application.Resources>
<ResourceDictionary>
...
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/YourNamespace;component/Themes/Amber.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
So here you'll see the MergedDictionaries element, this is where the magic happens. If you run the app now, you should see that any buttons will have a background colour of Amber. Cool, huh?
Now it gets a little bit trickier, we will be removing the resource dictionary that is currently in the dictionary and replacing it with a different theme (a different resource dictionary).
Here is some C# to do that:
Disclaimer: I just threw this code together, there is almost certainly a better way, but you get the idea. Put the following code in a mouse click event, or somewhere where you can step it through to see what's happening.
Firstly, remove the current theme from the merged dictionaries.
//Find the current dictionary
ResourceDictionary oldDictionary = App.Current.Resources.MergedDictionaries.FirstOrDefault();
//If we found one, remove it.
if (dictionary != null)
App.Current.Resources.MergedDictionaries.Remove(oldDictionary);
Now we just need to add a different resource dictionary. I'm just going to add the Blue theme for the sake of an example:
//Declare some variables.
string folderPath = "/YourNamespace;component/Themes/";
string desiredTheme = "Blue";
//Create the new resource dictionary
ResourceDictionary newDictionary = new ResourceDictionary();
newDictionary.Source = new Uri(string.Format("{0}{1}.xaml", folderPath, desiredTheme), UriKind.RelativeOrAbsolute);
//Add the resource dictionary to the merged dictionaries.
App.Current.Resources.MergedDictionaries.Add(newDictionary);
Now if all goes well, the background for any buttons in your app should now be Blue. Hooray!
Using this method, which in essence is creating multiple resource dictionaries each with resources under the same name, you can create multiple themes for your application. This isn't restricted to colours, you can have entire styles which are theme specific, where one theme might display a button in a completely different way as another style. Experiment and see what you can come up with. Good luck!
I am reading up about the ResourceDictionary and have come to a confusing point.
It appears I can only have 1 ResourceDictionary per XAML. So, if I wanted to use more than one, I can Merge the ResourceDictionaries.
If I can merge dictionaries then where should 'global' styles live? I could have an ApplicationResourceDictionary with all the styles which are to be consistent throughout my application OR, I could save this information into the App.xaml file. both appear to be valid options but I don't know if that is the case.
Is this about personal choice or is one better than the other? It would appear keeping them in ResourceDictionaries is better because all styles are together (within the dictionaries) instead of splitting some in XAML pages.
Our current solution has 100+ projects in it. Each needing access to a few Resource Dictionaries with global resources for themes and uniformity etc. What I do for it is have the resource dictionaries centrally located in one project the others reference, in this case we call it "infrastructure" then I supply the dictionaries to each proj directly via their own app.xaml with merged dictionaries like for example;
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Our.Client.Infrastructure;component/Resources/Styles/ResDictName1.xaml" />
<ResourceDictionary Source="/Our.Client.Infrastructure;component/Resources/Styles/ResDictName2.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Which so far works splendidly, the way I make the styles apply global though is specifying them as such at the bottom of one of our custom Resource Dictionaries and remove the same declaration from the Default Resource Dictionaries. So for example if you find;
<Style BasedOn="{StaticResource DefaultButtonStyle}" TargetType="Button" />
in your Default CoreStyles.xaml or SdkStyles.xaml or whatever they may be, I just remove it, and move that declaration over to the bottom of our custom Resource Dictionary and change it accordingly like;
<Style BasedOn="{StaticResource OurSuperAwesomeCustomNewGlobalButtonStyle}" TargetType="Button" />
and voila... Any Button thereafter inherits our custom style by default instead of the original default template. The advantages of having just one or two Resource Dictionaries for your entire solution become clear real quick once you adopt it. That is, provided the template actually needs to be globally available. If you're using a template for something adhoc that only pertains to the view its used on, keep it in that view explicitly, no need to keep it somewhere else if nothing else needs it.
Hope this helps.