Silverlight Style : custom style based on custom style - silverlight

Someone has done a custom style for the buttons of the application. Now I want to create a custom style based on this custom style. For example I want to make a "close button" that I want to reuse all other the application. I tried this :
<Style x:Key="GlassButtonClose" TargetType="Button" BasedOn="{StaticResource GlassButton}">
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Grid.Row="0" Source="/Balisage;component/Images/Close.png" Width="24" Height="24" />
<TextBlock Grid.Column="1" VerticalAlignment="Center" Text="{Binding Source={StaticResource LocCommonStrings}, Path=ButtonLabelClose}" Margin="0" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
But this doesn't keep the GlassButton settings. How can I just extend the settings, keeping the existing ones ?
Thanks for your help

Based on the shown template and your answer in the comments it looks like you only need to have a spacific GlassButton with a fixed icon and text. And you want to use this button without the need to specify its content again and again.
Solution:
Prepare your own type GlassStyleCloseButton.
public class GlassStyleCloseButton : Button
{
public GlassStyleCloseButton() {
DefaultStyleKey = typeof(GlassStyleCloseButton); }
}
and a style for the new type (can be placed in app.xaml or generic.xaml):
<Style TargetType="GlassStyleCloseButton" BasedOn="{StaticResource GlassButton}">
<Setter Property="Content" Value="{Binding Path=ButtonLabelClose,
Source={StaticResource LocCommonStrings}}"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image
Source="/Balisage;component/Images/Close.png"
Width="24"
Height="24"/>
<TextBlock
Grid.Column="1"
VerticalAlignment="Center"
Text="{TemplateBinding Content}"/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
and you can use it like this:
<SomewhereInMyApp>
...
<GlassStyleCloseButton/>
</SomewhereInMyApp>

Related

How to keep a button to the right of a datagrid header

I want to add a button to the datagrid header column and keep it at the right-most edge of the header column... no matter how wide it is. In my Xaml code I am using a DataTemplate where I attach the header column title and add a toggle button with a popup window.
<DataGrid>
<DataGrid.Resources>
<DataTemplate x:Key="HeaderTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<DataGrid.Resources>
<ContentControl Content="{Binding}" VerticalAlignment="Center"/>
<!--TODO: THIS IS THE BUTTON I WANT TO ANCHOR TO THE RIGHT-->
<ToggleButton Name="FilterButton" Grid.Column="1" Content="▼" Margin="2, 1, 1, 1" Padding="1, 0"/>
<Popup IsOpen="{Binding ElementName=FilterButton, Path=IsChecked}" PlacementTarget="{Binding ElementName=FilterButton}" StaysOpen="False">
<Border Background="White" Padding="3">
<TextBox Width="300"/>
</Border>
</Popup>
</Grid>
</DataTemplate>
</DataGrid.Resources>
When I launch my application I do see the header column with the toggle button right next to it. But I need it to be in the rightmost of any column header. Like this:
Can someone help me understand how to go about doing this with the code I currently have?
After a bit of fiddling, here's what I did to get it to work:
<DataGrid>
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
<DataTemplate x:Key="HeaderTemplate">
<Grid Margin="0, 0, -5, 0">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentControl Content="{Binding}" VerticalAlignment="Center"/>
<!--TODO: THIS IS THE BUTTON I WANT TO ANCHOR TO THE RIGHT-->
<ToggleButton Name="FilterButton" Grid.Column="1" Content="▼" Margin="2, 1, 1, 1" Padding="1, 0"/>
<Popup IsOpen="{Binding ElementName=FilterButton, Path=IsChecked}" PlacementTarget="{Binding ElementName=FilterButton}" StaysOpen="False">
<Border Background="White" Padding="3">
<TextBox Width="300"/>
</Border>
</Popup>
</Grid>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn HeaderTemplate="{StaticResource HeaderTemplate}" Header="Test"/>
</DataGrid.Columns>
</DataGrid>
There are two key changes.
First, I added this to DataGrid.Resources:
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
Which lets the HeaderTemplate fill the the entire header.
Second, I added a negative right margin to the Grid:
<Grid Margin="0, 0, -5, 0">
This compensates for the internal padding of the header's control template, moving the button fully to the right.
The problem here is that the content inside the header is Autosized. What you need to do is to change the Horizontal Alignment of the content. You can define a style for Column header and that will resolve the issue.
<DataGrid.Resources>
<Style TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</DataGrid.Resources>

Adjusting WPF chart toolkit ColumnSeries (System.Windows.Controls.DataVisualization.Charting)

I am using the WPF chart toolkit (System.Windows.Controls.DataVisualization.Charting). All stylings are in the XAML and I only bound the data to chart from my ViewModel. Everything looks alright for the first time I click on a button to show the columnseries. When I click on the button for the second time, the chart becomes bigger/corrupted; It shows only part of the graph.
The graph is drawn for the first time:
And button clicked for the second time:
The code I am using is as below:
<dvc:Chart Cursor="Cross"
Background="#FFFFFCF2"
Title="{Binding Title}"
Height="410"
Width="750"
VerticalAlignment="Top"
Name="ChartContainer">
<dvc:Chart.Series>
<dvc:ColumnSeries ItemsSource="{Binding ChartData,UpdateSourceTrigger=PropertyChanged}"
IndependentValueBinding="{Binding Path= Key}"
DependentValueBinding="{Binding Path= Value}"
Name="SummariesChart"
Margin="0,0,0,0"
IsManipulationEnabled="False">
<dvc:ColumnSeries.DataPointStyle>
<Style TargetType="dvc:ColumnDataPoint">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="dvc:ColumnDataPoint">
<Grid>
<Rectangle Fill="{TemplateBinding Background}"
Stroke="Black" />
<Grid Margin="0,0, 0, 0"
HorizontalAlignment="Center"
VerticalAlignment="Top">
<TextBlock Text="{TemplateBinding FormattedDependentValue}"
Margin="2" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</dvc:ColumnSeries.DataPointStyle>
</dvc:ColumnSeries >
</dvc:Chart.Series >
<dvc:Chart.Axes>
<dvc:LinearAxis Orientation="X"
Title="{Binding XTitle}"
Interval="1"
Location="Bottom"
ShowGridLines="True" />
<dvc:LinearAxis Orientation="Y"
Title="{Binding YTitle}"
ShowGridLines="True"
Location="Left" />
</dvc:Chart.Axes>
</dvc:Chart>
Also, to give you complete idea, I used a style on top of the page as follow:
<Style TargetType="dvc:Chart">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="dvc:Chart">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<dv:Title Content="{TemplateBinding Title}"
Style="{TemplateBinding TitleStyle}"
Margin="1" />
<Grid Grid.Row="1"
Margin="1,0,1,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<primitives:EdgePanel x:Name="ChartArea">
<Grid Canvas.ZIndex="-1"
Style="{TemplateBinding PlotAreaStyle}" />
<Border Canvas.ZIndex="10"
BorderBrush="#FF919191"
BorderThickness="1" />
</primitives:EdgePanel>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="BarDataPointStyle"
TargetType="{x:Type dvc:BarSeries}">
<Setter Property="Background"
Value="Blue"></Setter>
<Setter Property="Opacity"
Value="0" />
</Style>
When I remove <dvc:Chart.Axes> block, it works correctly consistently. But I need X-axe and Y-axes descriptions existing in this code block. Do you know how I can tackle this problem? I appreciate your help.
I found a way to resolve the issue. But still, I am skeptical that something is wrong with the styling or something.
I added Minimum = 0 and Maximum in LinearAxis tag. I bounded Maximum to a variable in my ViewModel. I got the length of the array and added one to the maximum variable(MaxNumberInXAxes).
<dvc:LinearAxis Orientation="X"
Title="{Binding XTitle}" I
nterval="{Binding XAxisInterval}"
Location="Bottom"
ShowGridLines="True"
AllowDrop="False"
Minimum="0"
Maximum="{Binding MaxNumberInXAxes}"/>
The graph becomes something like this:

Binding with ElementName in Style setter

I have a base style for Button which contains the ControlTemplate, then I want to create a few styles based on that which just set the Content for commonly used things like "OK", "Cancel", etc.
In those styles I have an image followed by some text, and I want to bind the height of the image to the height of the text, so I've got the following:
<Style x:Key="OkayButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource RoundedButtonStyle}">
<Setter Property="Content">
<Setter.Value>
<Grid HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{DynamicResource OkayIcon}" Height="{Binding ActualHeight, ElementName=ButtonText}"/>
<TextBlock x:Name="ButtonText" Grid.Column="1" Margin="5,0,0,0" Text="Okay"/>
</Grid>
</Setter.Value>
</Setter>
</Style>
Doing that gives me the error:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=ButtonText'. BindingExpression:Path=ActualHeight; DataItem=null; target element is 'Image' (Name=''); target property is 'Height' (type 'Double')
I'm guessing it's trying to find ButtonText in the ControlTemplate which it obviously can't. Is there a way to accomplish what I'm trying to do here and bind to another element's property from within this style setter?
I don't know why that binding is not working for you; perhaps because name resolution visual tree something or other.
But this works for me, and also addresses the shared-resource issue I mentioned in comments.
<DataTemplate x:Key="ButtonContent" >
<Grid HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
Source="{DynamicResource OkayIcon}"
Height="{Binding ActualHeight, ElementName=ButtonText}"
/>
<TextBlock
x:Name="ButtonText"
Grid.Column="1"
Margin="5,0,0,0"
Text="Okay"
FontSize="32"
/>
</Grid>
</DataTemplate>
<Style
x:Key="OkayButtonStyle"
TargetType="{x:Type Button}"
BasedOn="{StaticResource RoundedButtonStyle}"
>
<Setter Property="ContentTemplate" Value="{StaticResource ButtonContent}" />
</Style>

XAML in WP8.1: Child Element Styles

I have a Grid and TextBlocks. I want to style all TextBlocks within the Grid. So I do this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="0,0,0,15" />
</Style>
</Grid.Resources>
<StackPanel Grid.Column="0">
<TextBlock Text="myText" Style="{StaticResource TitleTextBlockStyle}" />
<TextBlock Text="myText" Style="{StaticResource TitleTextBlockStyle}" />
</StackPanel>
<StackPanel Grid.Column="1">
<TextBlock Text="123456" Style="{StaticResource TitleTextBlockStyle}" Foreground="{ThemeResource PhoneAccentBrush}" />
<TextBlock Text="123456" Style="{StaticResource TitleTextBlockStyle}" Foreground="{ThemeResource PhoneAccentBrush}" />
</StackPanel>
</Grid>
1) It's not working. TextBlocks don't get any Margins. Why?
2) How can I set the Style and Foreground properties of TextBlocks in the <Grid.Resources> tag?
1) It's not working. TextBlocks don't get any Margins. Why?
It's not working because you're assigning the style "TitleTextBlockStyle" to the TextBlocks. So the implicit style you defined in Grid.Resources doesn't come in to play. Remove the Style="{StaticResource TitleTextBlockStyle}" parts from the TextBlocks, and your margins will appear.
2) How can I set the Style and Foreground properties of TextBlocks in the <Grid.Resources> tag?
The same as you set everything else:
<Setter Property="Foreground" Value="AliceBlue"/>
or if you have a more elaborate brush:
<Setter Property="Foreground">
<Setter.Value>
<!-- Whatever brush you want -->
<Setter.Value/>
</Setter>
I assume that with "Set the style property of TextBlocks", you actually want your new style to inherit from an already defined style. In that case you can base your new style on an already existing style:
<Style TargetType="TextBlock"
BasedOn="{StaticResource StyleToInheritFrom}">
or, in your case, presumably:
<Style TargetType="TextBlock" BasedOn="{StaticResource TitleTextBlockStyle}">
<Setter Property="Margin" Value="0,0,0,15" />
</Style>
The full thing would look something like:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource TitleTextBlockStyle}">
<Setter Property="Margin" Value="0,0,0,15" />
<Setter Property="Foreground" Value="{ThemeResource PhoneAccentBrush}"/>
</Style>
</Grid.Resources>
<StackPanel Grid.Column="0">
<TextBlock Text="myText" />
<TextBlock Text="myText" />
</StackPanel>
<StackPanel Grid.Column="1">
<TextBlock Text="123456" />
<TextBlock Text="123456" />
</StackPanel>
</Grid
What sort of margins are you looking for? If you are looking for left right margins, its due to your margin declaration. Declare like this:
<object Margin="left,top,right,bottom"/>
- or -
<object Margin="left,top"/>
- or -
<object Margin="thicknessReference"/>
Right now, you're just adding a bottom margin. You could also just add
Margin="15"
which will be interpreted as a thickness reference and set all values to 15

16x16 pixel images in RibbonApplicationMenuItem gets stretched

I am having a ribbon application menu that looks like this:
<ribbon:RibbonWindow>
<DockPanel>
<ribbon:Ribbon DockPanel.Dock="Top">
<ribbon:Ribbon.ApplicationMenu>
<ribbon:RibbonApplicationMenu>
<ribbon:RibbonApplicationMenuItem Header="Users"
ImageSource="Users16x16.png"
Command="{Binding FooBinding}"/>
</ribbon:RibbonApplicationMenu>
</ribbon:Ribbon.ApplicationMenu>
</ribbon:Ribbon>
</DockPanel>
</ribbon:RibbonWindow>
The resulting image looks like this, stretched.
So how do I have a ribbon application menu item with a height that adapts to the image size instead of stretching?
Change the control template like:
<ribbon:RibbonApplicationMenuItem Command="{Binding FooBinding}">
<ribbon:RibbonApplicationMenuItem.Template>
<ControlTemplate>
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="Users16x16.png"/>
<TextBlock Grid.Column="1">Users</TextBlock>
</Grid>
</ControlTemplate>
</ribbon:RibbonApplicationMenuItem.Template>
</ribbon:RibbonApplicationMenuItem>
If you want to use control template as Style in your dictionary:
<Style x:Key="16x16ImageStyle" TargetType="{x:Type ribbon:RibbonApplicationMenuItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ribbon:RibbonApplicationMenuItem}">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="None"
Grid.Column="0" Source="{TemplateBinding ImageSource}"/>
<TextBlock Grid.Column="1" Text="{TemplateBinding Header}"></TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and recall it in your ribbon:
<ribbon:RibbonApplicationMenuItem Header="Users"
ImageSource="Users16x16.png"
Command="{Binding FooBinding}"
Style="{StaticResource 16x16ImageStyle}"/>

Resources