NB this was for the silverlight 3 beta, RTM seems to handle grouping entirely differently.
I've a grid that is working fine, which I'm using the GroupDescriptions property like so:
<data:DataGrid.GroupDescriptions>
<cm:PropertyGroupDescription PropertyName="ClientName" />
</data:DataGrid.GroupDescriptions>
This works brilliantly, it's only when the datagrid is rendered, it shows the grouping by "ClientName". Obviously I'd like that to be "Client Name". I cannot for the life of me see a property that would allow me to set this?
FWIW this has changed in SL3 RTM:
Silverlight 3 Beta
[Xaml]
<dataGrid.GroupDescriptions>
<windata:PropertyGroupDescription PropertyName=”State” />
</dataGrid.GroupDescriptions>
Silverlight 3 RTM
[c#]
pagedCollectionView.GroupDescriptions.Add(new PropertyGroupDescription(“State”));
You need to use the PagedCollectionView class to accomplish this, it can't be done in Xaml anymore. See http://msdn.microsoft.com/en-us/library/dd833072(VS.95).aspx
And from that link, here's how to change the text in the group header:
When items are grouped in the DataGrid, each group has a header. You can change the appearance of the DataGridRowGroupHeader by defining a custom Style and adding it to the RowGroupHeaderStyles collection. If you have multiple levels of grouping, you can apply different styles to each group level. Styles are applied in the order in which they are defined. For example, if you define two styles, the first will be applied to top level row groups. The second style will be applied to all row groups at the second level and lower. The DataContext of the DataGridRowGroupHeader is the CollectionViewGroup that the header represents.
So a quick and dirty example would be:
<dataControls:DataGrid x:Name="Grid">
<dataControls:DataGrid.RowGroupHeaderStyles>
<Style TargetType="dataControls:DataGridRowGroupHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock Text="My text."/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</dataControls:DataGrid.RowGroupHeaderStyles>
</dataControls:DataGrid>
In practice you probably want to include the other control parts that are specified for DataGridRowGroupHeader so that you can expand and collapse them. As with everything WPF, instead of just setting a "GroupText" property you have to go whole 9 yards!
Having the same problem as DaRKoN_ and having read James Cadd insightful answer I solved my own problem. By using Blend I have extracted the template for the DataGridRowGroupHeader. You can use the code below to customize it:
<data:DataGrid>
<data:DataGrid.RowGroupHeaderStyles>
<Style TargetType="data:DataGridRowGroupHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="data:DataGridRowGroupHeader">
<dataPrimitives:DataGridFrozenGrid x:Name="Root" Background="{TemplateBinding Background}">
<dataPrimitives:DataGridFrozenGrid.Resources>
<ControlTemplate x:Key="ToggleButtonTemplate" TargetType="ToggleButton">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" Storyboard.TargetName="CollapsedArrow" Storyboard.TargetProperty="(Stroke).Color" To="#FF6DBDD1"/>
<ColorAnimation Duration="0" Storyboard.TargetName="ExpandedArrow" Storyboard.TargetProperty="(Fill).Color" To="#FF6DBDD1"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0" Storyboard.TargetName="CollapsedArrow" Storyboard.TargetProperty="(Stroke).Color" To="#FF6DBDD1"/>
<ColorAnimation Duration="0" Storyboard.TargetName="ExpandedArrow" Storyboard.TargetProperty="(Fill).Color" To="#FF6DBDD1"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="CollapsedArrow" Storyboard.TargetProperty="Opacity" To=".5"/>
<DoubleAnimation Duration="0" Storyboard.TargetName="ExpandedArrow" Storyboard.TargetProperty="Opacity" To=".5"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked"/>
<VisualState x:Name="Unchecked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="CollapsedArrow" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="ExpandedArrow" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Path x:Name="CollapsedArrow" Stretch="Uniform" Stroke="#FF414345" HorizontalAlignment="Center" VerticalAlignment="Center" Width="5" Visibility="Collapsed" Data="F1 M 0,0 L 0,1 L .6,.5 L 0,0 Z"/>
<Path x:Name="ExpandedArrow" Fill="#FF414345" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Center" Width="6" Data="F1 M 0,1 L 1,1 L 1,0 L 0,1 Z"/>
</Grid>
</ControlTemplate>
</dataPrimitives:DataGridFrozenGrid.Resources>
<dataPrimitives:DataGridFrozenGrid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</dataPrimitives:DataGridFrozenGrid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CurrentStates">
<VisualState x:Name="Regular"/>
<VisualState x:Name="Current">
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="FocusVisual" Storyboard.TargetProperty="Opacity" To="1"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<dataPrimitives:DataGridFrozenGrid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</dataPrimitives:DataGridFrozenGrid.RowDefinitions>
<Rectangle Fill="#FFFFFFFF" Height="1" Grid.Column="1" Grid.ColumnSpan="5"/>
<Rectangle x:Name="IndentSpacer" Grid.Column="1" Grid.Row="1"/>
<ToggleButton x:Name="ExpanderButton" Height="15" Margin="2,0,0,0" Width="15" Template="{StaticResource ToggleButtonTemplate}" Grid.Column="2" Grid.Row="1"/>
<StackPanel Margin="0,1,0,1" VerticalAlignment="Center" Grid.Column="3" Grid.Row="1" Orientation="Horizontal">
<TextBlock x:Name="PropertyNameElement" Margin="4,0,0,0" Visibility="{TemplateBinding PropertyNameVisibility}"/>
<TextBlock Margin="4,0,0,0" Text="{Binding Name}"/>
<TextBlock x:Name="ItemCountElement" Margin="4,0,0,0" Visibility="{TemplateBinding ItemCountVisibility}"/>
</StackPanel>
<Rectangle Fill="#FFD3D3D3" Height="1" Grid.Column="1" Grid.ColumnSpan="5" Grid.Row="2"/>
<Rectangle x:Name="FocusVisual" Stroke="#FF6DBDD1" StrokeThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" IsHitTestVisible="false" Opacity="0" Grid.Column="1" Grid.ColumnSpan="4" Grid.RowSpan="3"/>
<dataPrimitives:DataGridRowHeader x:Name="RowHeader" Grid.RowSpan="3" dataPrimitives:DataGridFrozenGrid.IsFrozen="True"/>
</dataPrimitives:DataGridFrozenGrid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</data:DataGrid.RowGroupHeaderStyles>
</data:DataGrid>
I have added blank lines before and after the TextBlock that contains the offending text. You can completely turn it off by using the following XAML:
<data:DataGrid>
<data:DataGrid.RowGroupHeaderStyles>
<Style TargetType="data:DataGridRowGroupHeader">
<Setter Property="PropertyNameVisibility" Value="Collapsed"/>
</Style>
<data:DataGrid.RowGroupHeaderStyles>
</data:DataGrid>
If you want to modify the text you will have both remove the name of the TextBlock and add a Text attribute:
<TextBlock Margin="4,0,0,0" Visibility="{TemplateBinding PropertyNameVisibility}" Text="Client Name:"/>
The DataGridRowGroupHeader will look for a TextBlock named PropertyNameElement and set the text from code, and to avoid that happening you will have to remove the name from the template.
I have implemented the template graciously provided by Martin Liversage (thanks!) but I can't seem to control the height of the group data row. Adjusting the size of the rectangles etc just takes up more room in the row, hiding other parts. It seems the row height is being controlled by the container for the row, outside the influence of the template.
TIA
Toby
Found the answer!
Refer to http://msdn.microsoft.com/en-us/library/cc278075(VS.95).aspx
This defines all the control styles and templates and zooming into the DataGrid and viewing the Default Template you will find:
<data:DataGrid.RowGroupHeaderStyles>
<Style TargetType="local:DataGridRowGroupHeader">
<Setter Property="Cursor" Value="Arrow" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Background" Value="#FFE4E8EA" />
<Setter Property="Height" Value="20"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:DataGridRowGroupHeader">
...snip...
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</data:DataGrid.RowGroupHeaderStyles>
Setting the Height property does the job.
Set the Name property of the Display attribute applied to the property you're grouping by:
[System.ComponentModel.DataAnnotations.Display( Name = "My Property" )]
public string MyProperty {get;set;}
looking at the Display class, one might think GroupName would be the property you set, but alas it it not.
I understand 'muddying up' the model with display data isn't always how everyone (myself included) likes to do things .. but in contrast to the amount of work required to do it in the above ways .. I think it wins out this time.
Related
I am working on a UWP windows 10 phone app and having trouble getting a storyboard to rotatetransform a path defined inside a buttons controltemplate.
I would prefer to acheive this in xaml. Do i specify for storyboard.targetproperty a quazi xaml path? => viewer.navbutton.PART_Arrow?
<Grid x:Name="layoutRoot" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.1"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="ShowNav">
<VisualState.Setters>
<Setter Target="navigation.(FrameworkElement.Height)" Value="Auto"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="HideNav">
<VisualState.Setters>
<Setter Target="navigation.(FrameworkElement.Height)" Value="0"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.Resources>
<Storyboard x:Name="rotateStoryBoard">
<DoubleAnimation Storyboard.TargetName="rotateDownArrow"
Storyboard.TargetProperty="Angle"
From="0"
To="90"
Duration="0:0:2"/>
</Storyboard>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Grid.Row="0" x:Name="navigation">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="1" x:Name="navbar" Margin="0,0,0,0"/>
<Button Grid.Column="0" x:Name="refresh_Copy"
VerticalAlignment="Top"
Content="Refresh"
Click="refresh_Click"
RenderTransformOrigin="1.457,0.562" />
</Grid>
<Grid Grid.Row="1" x:Name="viewer">
<Button x:Name="navButton"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Canvas.ZIndex="1"
Click="navButton_Click">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid HorizontalAlignment="Center">
<Path x:Name="PART_Circle"
Fill="{ThemeResource ButtonBackgroundThemeBrush}"
Stroke="{ThemeResource ButtonBackgroundThemeBrush}"
StrokeThickness="1.5"
Data="M0,0 A30,30 0 0 0 60,0"/>
<Path x:Name="PART_Arrow"
Stroke="GreenYellow"
StrokeThickness="1.5"
Data="M12,6 L30,18 L48,6">
<Path.RenderTransform>
<RotateTransform x:Name="rotateDownArrow"
Angle="0"
CenterX="30"
CenterY="12"/>
</Path.RenderTransform>
</Path>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
<WebView x:Name="Web"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
NavigationCompleted="Web_NavigationCompleted"
ScriptNotify="Web_OnScriptNotify"
Canvas.ZIndex="0"/>
</Grid>
</Grid>
What is the correct syntax for a storyboard to access a path in a controltemplate?
The Path control you want to access is inside a ControlTemplate. According to the XAML name scopes in templates section of this article:
Templates in XAML provide the ability to reuse and reapply content in a straightforward way, but templates might also include elements with names defined at the template level. That same template might be used multiple times in a page. For this reason, templates define their own XAML name scopes, independent of the containing page where the style or template is applied.
So the ControlTemplate has its own namescopes, you cannot directly access a control inside it by Name. You may need to use VisualTreeHelper class to help you access the controls.
But if you want a storyboard can access the control, you can let the storyboard in a same template with the control and they will be in a same scope.
In additionally, Button control template contains four default VisualStates, trigger the storyboard by one visual state may be recommended. The following code put the storyboard into the ControlTemplate and it is triggered when the button is pressed that you can reference.
<Grid
x:Name="layoutRoot"
Padding="50"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
...
<Grid x:Name="viewer" Grid.Row="1">
<Button
x:Name="navButton"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Canvas.ZIndex="1"
Click="navButton_Click">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid HorizontalAlignment="Center">
<Grid.Resources>
<Storyboard x:Name="rotateStoryBoard">
<DoubleAnimation
BeginTime="0:0:0"
Duration="0:0:2"
From="0"
Storyboard.TargetName="rotateDownArrow"
Storyboard.TargetProperty="Angle"
To="90" />
</Storyboard>
</Grid.Resources>
<Path
x:Name="PART_Circle"
Fill="{ThemeResource ButtonBackgroundThemeBrush}"
Stroke="{ThemeResource ButtonBackgroundThemeBrush}"
StrokeThickness="1.5"
Data="M0,0 A30,30 0 0 0 60,0" />
<Path
x:Name="PART_Arrow"
Stroke="GreenYellow"
StrokeThickness="1.5"
Data="M12,6 L30,18 L48,6">
<Path.RenderTransform>
<RotateTransform x:Name="rotateDownArrow" Angle="0" CenterX="30" CenterY="12" />
</Path.RenderTransform>
</Path>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation
BeginTime="0:0:0"
Duration="0:0:2"
From="0"
Storyboard.TargetName="rotateDownArrow"
Storyboard.TargetProperty="Angle"
To="90" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
...
</Grid>
I am trying to use the VisualStateManager inside my ControlTemplate for a ToggleButton. I want the ToggleButton to look one way when checked and another when unchecked. I also want the ToggleButton to look different when it's disabled. The issue I'm having is the Unchecked VisualState seems to be trumping the Disabled VisualState.
The documentation states that "Each VisualStateGroup contains a collection of VisualState objects that are mutually exclusive." That's nice, but what about mutual exclusivity between groups?
Anyhow, here's my ControlTemplate. How can I get the TextBlock to use different color for each of the three states; Checked, Unchecked and Disabled?
<Style x:Key="GraphToggleButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="TextBlock" To="Pink" Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="TextBlock" To="#3AA5DB" Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="TextBlock" To="Green" Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" CornerRadius="4" Background="{TemplateBinding Background}">
<StackPanel>
<TextBlock Name="TextBlock" FontFamily="/Resources/#Entypo" Text="🔆" FontSize="87" Foreground="#909090" HorizontalAlignment="Center" Margin="0,-25,0,0" />
<TextBlock FontFamily="Proxima Nova Rg" Text="Stimulator" FontSize="18" Foreground="{StaticResource BlackBrush}" HorizontalAlignment="Center" Margin="0,12,0,0" />
</StackPanel>
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Each VisualStateGroup contains a collection of VisualState objects that are mutually exclusive
This is actually true. However there is still one more requirement, that's each VisualState should not affect the same properties. In this case your Unchecked state and Disabled state affect the same property Foreground of the same element.
So I don't think we can have any elegant solution for this. We just have this work-around (this is in fact used commonly when styling element in WPF). We need some fake element called DisabledTextBlock, this should be placed in the same Grid with the original element TextBlock. Once the Disabled state comes, that fake element should be shown and hide the original one as well as hide all the effect of the Unchecked (or Checked) state and bring the effect of Disabled to the front. Here is the working code:
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<!-- unchanged -->
</VisualStateGroup>
<VisualStateGroup x:Name="CommonStates">
<VisualState Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="DisabledTextBlock" To="1" Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" CornerRadius="4" Background="{TemplateBinding Background}">
<StackPanel>
<Grid>
<TextBlock Name="TextBlock" FontFamily="/Resources/#Entypo" Text="🔆"
FontSize="87" Foreground="#909090" HorizontalAlignment="Center"
Margin="0,-25,0,0" Background="Transparent"/>
<!-- the fake element -->
<TextBlock Name="DisabledTextBlock" Opacity="0"
FontFamily="{Binding FontFamily, ElementName=TextBlock}"
Text="{Binding Text,ElementName=TextBlock}"
FontSize="{Binding FontSize,ElementName=TextBlock}"
Foreground="Pink" HorizontalAlignment="Center"
Margin="{Binding Margin, ElementName=TextBlock}"
Background="Transparent"
FontStyle="{Binding FontStyle,ElementName=TextBlock}"
FontWeight="{Binding FontSize, ElementName=TextBlock}"/>
</Grid>
<TextBlock FontFamily="Proxima Nova Rg" Text="Stimulator" FontSize="18"
Foreground="Black" HorizontalAlignment="Center" Margin="0,12,0,0"/>
</StackPanel>
</Border>
</Border>
</ControlTemplate>
You may have some new requirement, however the idea here is clear. That's the only work-around I think.
I'm trying to animate the content of a metro styled button.
My problem is that the content of the button does not change color.
The foreground color does not change.
Here's my button's style:
<Style x:Key="MetroButtonStyle"
TargetType="Button">
<Setter Property="MinWidth"
Value="40"/>
<Setter Property="Width"
Value="100"/>
<Setter Property="MinHeight"
Value="88"/>
<Setter Property="HorizontalAlignment"
Value="Center"/>
<Setter Property="Foreground"
Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="AppButton"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Duration="0"
To="1"
Storyboard.TargetProperty="(UIElement.Opacity)"
Storyboard.TargetName="MouseOverEllipse"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation Duration="0"
To="1"
Storyboard.TargetProperty="(UIElement.Opacity)"
Storyboard.TargetName="PressedEllipse"/>
<ColorAnimation Duration="0"
To="Black"
Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="EllipseInnerContent"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimation Duration="0"
To="#7F8D8D8D"
Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="EllipseInnerContent"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel Orientation="Vertical"
HorizontalAlignment="Center">
<Grid Margin="0,14,0,5"
HorizontalAlignment="Center"
MinWidth="40">
<Ellipse x:Name="PressedEllipse"
Fill="{TemplateBinding Foreground}"
Opacity="0"
Width="40"
Height="40"/>
<Ellipse x:Name="MouseOverEllipse"
Fill="#7F8D8D8D"
Opacity="0"
Width="40"
Height="40"/>
<Ellipse Fill="Transparent"
Stroke="{TemplateBinding Foreground}"
StrokeThickness="2"/>
<ContentPresenter x:Name="EllipseInnerContent"
Content="{TemplateBinding Content}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
<TextBlock x:Name="LabelText"
TextWrapping="Wrap"
HorizontalAlignment="Center"
FontFamily="Segoe UI"
FontSize="12"
Text="{TemplateBinding Tag}"
Foreground="{TemplateBinding Foreground}"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Here's is how i use it.
This does not works:
<Button Style="{StaticResource MetroButtonStyle}"
Tag="Blah">
<TextBlock Text="XXX"/>
</Button>
This works:
<Button Style="{StaticResource MetroButtonStyle}"
Tag="Blah"
Content="XXX"/>
You have
Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="EllipseInnerContent"
in your animations, where EllipseInnerContent is a ContentPresenter and there's no Foreground property on ContentPresenter.
Change it to ContentControl.
Also, when putting a TextBlock as a content of a control, it will inherit the foreground of the page\user control that it's part of. Use DataTemplate instead to have the TextBlock created for you and then it will inherit the foreground from the button.
I have a Border element on my page that contains some TextBlock elements contained in a grid, e.g. (simplified):
<Border Style="{StaticResource borderStyle}">
<Grid Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="Something" Grid.Column="0" Grid.Row="0" />
<TextBlock Text="Something else" Grid.Column="1" Grid.Row="0" />
</Grid>
</Border>
I have the following style defined:
<Style x:Key="borderStyle" TargetType="Border">
<Setter Property="CornerRadius" Value="0,0,15,15"/>
<Setter Property="Background" Value="Black"/>
<Setter Property="Opacity" Value="0.6"/>
</Style>
How would I add a VisualStateGroup (or something similar) to the style to change the opacity on mouseover? I can't seem to get it working for a Border element, is there a reason for this?
VSM will work inside ControlTemplate alone. Thats the reason. There is no template there that is the reason you are not able to get it working.
Alternatively, you can use EventTriggers. Like below.
<Grid x:Name="LayoutRoot" Background="White">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0">
<Storyboard/>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOverState">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderThickness)" Storyboard.TargetName="border">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Thickness>3</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="border" BorderBrush="Black" BorderThickness="1" Height="143" Margin="164,79,191,0" VerticalAlignment="Top">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<ei:GoToStateAction StateName="MouseOverState" TargetObject="{Binding ElementName=userControl}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Border>
</Grid>
I am trying to use a DataTemplate for ListBox.ItemTemplate for a simple TODO list.
The template for each ListBoxItem is a grid and I want the content for my 2nd column to stretch the remaining width of the listbox. No amount of HorizontalAlignment="Stretch" etc. etc. seems to do the trick and I think I need to modify the template. I've looked at the ListBox extracted Xaml template but cannot see what I need to change.
In this XAML sample you can see a green box that is supposed to stretch the remaining width of the listboxitem, but doesn't.
In XamlPad / WPF this code actually DOES render as expected.
In Silverlight though the box won't stretch.
<ListBox Width="360" Height="150" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="3,0,3,0" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="URGENT" Foreground="Red" Margin="5,0,10,0" Grid.Column="0" VerticalAlignment="Center"/>
<Border BorderBrush="Green" BorderThickness="1" Grid.Column="1" HorizontalAlignment="Stretch" Margin="0,2">
<TextBlock Margin="5,2" Text="{Binding}" FontWeight="Bold" />
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
<s:String>Take out trash</s:String>
<s:String>Clean car</s:String>
<s:String>Finish TODO list program</s:String>
<s:String>Sleep</s:String>
</ListBox>
You can achieve what you want by defining a ItemContainerStyle for your ListBox :
<Style x:Key="ListBoxItemStyle1" TargetType="ListBoxItem">
<Setter Property="Padding" Value="3"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="TabNavigation" Value="Local"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Duration="0" To=".35" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="fillColor"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To=".55" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="contentPresenter"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<DoubleAnimation Duration="0" To=".75" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="fillColor2"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusVisualElement">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid HorizontalAlignment="Stretch" Margin="3,0,3,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="URGENT" Foreground="Red" Margin="5,0,10,0" Grid.Column="0" VerticalAlignment="Center"/>
<Border BorderBrush="Green" BorderThickness="1" Grid.Column="1" HorizontalAlignment="Stretch" Margin="0,2">
<TextBlock Margin="5,2" Text="{Binding}" FontWeight="Bold" />
</Border>
</Grid>
<Rectangle x:Name="fillColor" Fill="#FFBADDE9" IsHitTestVisible="False" Opacity="0" RadiusY="1" RadiusX="1"/>
<Rectangle x:Name="fillColor2" Fill="#FFBADDE9" IsHitTestVisible="False" Opacity="0" RadiusY="1" RadiusX="1"/>
<Rectangle x:Name="FocusVisualElement" RadiusY="1" RadiusX="1" Stroke="#FF6DBDD1" StrokeThickness="1" Visibility="Collapsed"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And then use this style in your listbox like this :
<ListBox Width="360" Height="150" x:Name="lb" HorizontalContentAlignment="Stretch" ItemContainerStyle="{StaticResource ListBoxItemStyle1}" />
In what you are trying to do , the problem is your grid width is not equivalent to the listbox item.
The problem is the Grid inside the DataTemplate, if you increase its size, you'll start to see that the border grows with it.