WinRT XAML Applying Style Inside DataTemplate - xaml

I have some styles that are being included in a page with a resource reference.
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
I have named styles for TextBlock, Button, etc. When using them, everything works fine.
When I try using them inside of a DataTemplate of an ItemsControl, they don't get applied.
<ItemsControl>
<ItemsControl.ItemsPanel>
<StackPanel Orientation="Horizontal" />
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="blah" Style="{StaticResource MyTextBlockStyle}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
How can I get the named styles that are included from another file to work inside my DataTemplate like it does everywhere else on the page?

Instead of including the styles in a particular page's XAML, include them in App.xaml. Here's how I add them
<Application x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Resources.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
I use style defined in Resources.xaml in DataTemplate all the time.

Instead of defining manually you can use Blend to through design panel.
When you right click to your
Gridview > Edit Additional Templates > Edit Generated Items
you can edit your content. Then you can select any of your item and define their style on design pane like below
If you don't see your button, textblock style in right click menu you can check this post to make them reusable
Style only works for the first occurence when outside Grid.Resources?
Hope this will be helpful.

Related

how to user color from global resources?

I want to set my resources on the app.xaml and then use it in the differents views of the app, but when I set the color the app crashes u.u, could someone help me ?
app.xaml
<Application.Resources>
<ResourceDictionary>
<Color x:Key="Primary">#FFC107</Color>
</ResourceDictionary>
</Application.Resources>
use it in a StackLayout
<StackLayout Orientation="Vertical" BackgroundColor="{StaticResource Primary}">
Has you called InitializeComponent in the App.xaml.cs?
you need to use Static Resource,I find a good resource for you:
https://blog.xamarin.com/easy-app-theming-with-xamarin-forms-styles/
So you need to do the following:
1- Define a ResourceDictionary at the app-level in App.xaml
<Application
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MonkeyTweet.App">
<Application.Resources>
<ResourceDictionary>
<Color x:Key="backgroundColor">#33302E</Color>
<Color x:Key="textColor">White</Color>
</ResourceDictionary>
</Application.Resources>
</Application>
2- Use StaticResource markup extension to reference predefined resources:
<Label Text="{Binding Text}" TextColor = "{StaticResource textColor}"/>
BackgroundColor="{DynamicResource Primary}"
its a DynamicResource, not a StaticResource.
Here's what my code looks like for example:
App.xaml has
<Color x:Key="titleColor">Green</Color>
and a page.xaml has
TextColor="{DynamicResource titleColor}"

x:Bind in resource dictionary doesn't work

I'm struggling to get a grip of the compiled databinding concept. I have one view (MainPage) that contains a ListBox and one data template (ItemTemplate) used for that ListBox. The MainPage has a MainPageViewModel that contains an ObservableCollection of ItemViewModels. The ItemViewModel contains only one property Name.
MainPage:
<Page x:Class="TestApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ItemDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListBox ItemsSource="{x:Bind ViewModel.Items}"
ItemTemplate="{StaticResource ItemTemplate}" />
</Grid>
</Page>
Resource dictionary containing datatemplate:
<ResourceDictionary
x:Class="TestApp.ItemDictionary"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp">
<DataTemplate x:Key="ItemTemplate" x:DataType="local:ItemViewModel">
<TextBlock Text="{x:Bind Name}" />
</DataTemplate>
</ResourceDictionary>
This code compiles but when I run it the binding to the Name property fails, although the items get generated. If I use a classic binding everything works fine and if I place the data template directly in the resources for the MainPage it also works. What am I missing?
Correct:
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<local:ItemDictionary />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
Incorrect:
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ItemDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>

ListView DataTemplate in separate folder

I'm trying to learn programming apps for Universal Windows Platform. I'm currently working with ListView and I define its layout in <DataTemplate>, but the code is a one mess. Is there a way to define <DataTemplate> in a separate folder? I searched the net but I wasn't able to find a solution. Could you please help me with that? Thanks.
I would always recommend creating a ResourceDictionary for this kind of thing. Here's an example setup:
Create a folder Resources > Add > New item > Resource Dictionary "Templates.xaml"
In your App.xaml add
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Templates.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
In Templates.xaml you can add any template you want, like so:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:thestory.Resources">
<DataTemplate x:Key="ListItemTemplate">
</DataTemplate>
You can now reference this template wherever you need it using {StaticResource ListItemTemplate}
Good Luck!
PS: I would actually also recommend doing the same for styles and other application wide resources like font sizes, brushes, backgrounds etc.
In datatemplate.xaml define datatemplate:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DataTemplate>
</DataTemplate>
</ResourceDictionary>
In UserControl refer to datatemplate:
<UserControl
x:Class="<assemblyName>.Themes.MyUserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PerpetuumSoft.DataManager.UniApp.UI.Themes"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ms-appx:///<AssemblyName>/Themes/DataTemplate.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
</Grid>
</UserControl>

Windows Store app's overriden resource value ignored in template

I'm creating a Windows Store app where each page has a dominant color used for titles, buttons and such.
In App.xaml I've created a default Brush that's overriden in each Page's xaml file, and a style template for Buttons which I reuse in every page. The templates are supposed to use the page's color but for some reason they stick with the default value.
Here are my xaml files.
App.xaml
<Application
x:Class="Foo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Foo"
RequestedTheme="Light">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<SolidColorBrush x:Name="SectionDefaultBrush" Color="Red" />
<Style TargetType="Button" x:Name="NavigationButtonStyle">
<Setter Property="FontFamily" Value="Myriad Pro" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Rectangle x:Name="Border" Fill="#f4f4f4" Margin="0" />
<TextBlock Foreground="{ ThemeResource SectionDefaultBrush }" Text=">" FontSize="31" />
<ContentPresenter x:Name="Content" VerticalAlignment="Center" Foreground="#5A5A5A" HorizontalAlignment="Left" FontSize="31"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
SomePage.xaml
<Page
x:Class="Foo.Pages.SomePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<SolidColorBrush x:Key="SectionDefaultBrush" Color="Green" />
</Page.Resources>
<ViewBox>
<Canvas>
<TextBlock Text="Some text" Foreground="{ ThemeResource SectionDefaultBrush }" Canvas.Left="130" TextWrapping="Wrap" Canvas.Top="252" Height="177" Width="507" FontFamily="Myriad Pro" FontSize="54" />
<Button Content="Click me" Style="{ ThemeResource NavigationButtonStyle }" Canvas.Left="130" Canvas.Top="900" Width="507" Height="48" />
</Canvas>
<ViewBox>
In this example, the TextBlock's text color is green as expected (and red if I remove the Brush from Page.Resources), but the Button's content remains red. Is there a way to tell the template to use the final color ?
The app's resource dictionary doesn't know about other dictionaries and unlike with WPF's DynamicResources - StaticResource isn't reevaluated and ThemeResource is, but I think only when the actual theme changes. The way you can customize the color of that button is to use TemplateBinding in the template and bind to say the Foreground property of the button and also set that in the Foreground Setter of your button style to {StaticResource SectionDefaultBrush}. Then in your page you can override that by setting the Foreground of the button to a different value or using a derived button style that changes the Foreground value.
Ideally too - you should define theme resources in your dictionary so the brushes change depending on OS theme (especially high contrast). You might want to name your brush then as "SectionDefaultThemeBrush" instead of just "SectionDefaultBrush".

How to reference a UI Element in a ResourceDictionary (Windows Store Apps)?

The following works as expected:
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<ResourceDictionary>
<Button x:Key="MyButton">Hello</Button>
</ResourceDictionary>
</Page.Resources>
<Grid>
<StaticResource ResourceKey="MyButton"/>
</Grid>
</Page>
This does not:
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<ResourceDictionary>
<Button x:Key="MyButton">Hello</Button>
</ResourceDictionary>
</Page.Resources>
<Grid>
<ItemsControl>
<StaticResource ResourceKey="MyButton"/>
</ItemsControl>
</Grid>
</Page>
(To reproduce, create a new Blank App in VS 2012 or VS 2013 RC and replace the content of MainPage.xaml with the above.)
I'm getting an unhandled exception with UnhandledExceptionEventArgs.Message = "Element is already the child of another element."
What am I doing wrong? Is this supposed to work?
Although it's not apparent here, I think I have a good reason to put some of my UI elements into a resource dictionary. I'm aware that each UI element can only ever appear in exactly one place, but even though this is the case in the second example, the error message claims otherwise.