Chris,
I don't know if you're still looking for a way to do this. I know that there are a lot of guides to similar problems, but not exactly what you're looking for. From my understanding of what you want, you want a control which has two faces (really x faces) where a user can push a button and cause the panel to "flip" and show different data. However, you want this data that is shown to be generic enough so that this flip panel can be used in other locations with just a different implementation rather than totally different code. Do I understand your needs correctly? If not, please clarify where I've gone astray and I can maybe get a better answer for you. With that being said, here is what I've done (Google code demo project at bottom):
- I created a control library that houses my FlipPanel (because that is how I do things; so that I may use the controls in other projects down the road.)
- I styled the control in the control library to contain the above described properties that you need in your scenario.
- I created a Silverlight 2.0 application to create an instance of the control.
- I created a basic object for binding that has a few properties so that I can demonstrate the control's potential.
Here is a possible definition to use in a Silverlight 2.0 page:
<Grid x:Name="LayoutRoot" Background="White">
<controls:FlipPanel x:Name="TestingFlipPanel" Side="Front" >
<controls:FlipPanel.BackDataTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Back: "/>
<TextBlock Text="{Binding BackText}" />
</StackPanel>
</DataTemplate>
</controls:FlipPanel.BackDataTemplate>
<controls:FlipPanel.FrontDataTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Front: "/>
<TextBlock Text="{Binding FrontText}" />
</StackPanel>
</DataTemplate>
</controls:FlipPanel.FrontDataTemplate>
</controls:FlipPanel>
</Grid>
The alternative to this is to define the data templates in the user control (page level, or even the app level) like this:
So that you have an idea of what my binding object looks like here is that definition (yes, it's VB... Sorry!):
Public Class BindingObject
Private _FrontText As String
Private _BackText As String
Public Sub New(ByVal frontText As String, ByVal backText As String)
MyBase.New()
_FrontText = frontText
_BackText = backText
End Sub
Public Property FrontText() As String
Get
Return _FrontText
End Get
Set(ByVal value As String)
_FrontText = value
End Set
End Property
Public Property BackText() As String
Get
Return _BackText
End Get
Set(ByVal value As String)
_BackText = value
End Set
End Property
End Class
In my code behind, here is the definition of my page and setting of the data context for the flip panel:
Partial Public Class Page
Inherits UserControl
Dim _BindingObject As New BindingObject("This is the front", "This is the back")
Public Sub New()
InitializeComponent()
End Sub
Private Sub Page_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
TestingFlipPanel.DataContext = _BindingObject
End Sub
End Class
So with this all laid out in front of you, we would expect that the control would display a button (in the control style) and a text block (actually two) that says "Front: This is the front" and when the button is pressed it is "flipped" to display "Back: This is the back".
With all that being said, here is the style that I used for the control:
<Style TargetType="controls:FlipPanel">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:FlipPanel">
<Grid x:Name="LayoutRoot">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button x:Name="FlipButton" Content="Flip" Grid.Row="0" />
<ContentPresenter Grid.Row="1" x:Name="FrontContentPresenter" Content="{TemplateBinding DataContext}" ContentTemplate="{TemplateBinding FrontDataTemplate}" />
<ContentPresenter Grid.Row="1" x:Name="BackContentPresenter" Content="{TemplateBinding DataContext}" ContentTemplate="{TemplateBinding BackDataTemplate}" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And finally, the control's definition (Caution - It's long):
<TemplatePart(Name:=FlipPanel.LayoutRoot_ElementName, Type:=GetType(FrameworkElement))> _
<TemplatePart(Name:=FlipPanel.FrontContentPresenter_ElementName, Type:=GetType(FrameworkElement))> _
<TemplatePart(Name:=FlipPanel.BackContentPresenter_ElementName, Type:=GetType(FrameworkElement))> _
<TemplatePart(Name:=FlipPanel.FlipButton_ElementName, Type:=GetType(FrameworkElement))> _
Public Class FlipPanel
Inherits Control
Public Const LayoutRoot_ElementName As String = "LayoutRoot"
Public Const FlipButton_ElementName As String = "FlipButton"
Public Const FrontContentPresenter_ElementName As String = "FrontContentPresenter"
Public Const BackContentPresenter_ElementName As String = "BackContentPresenter"
Public Enum Sides
Front
Back
End Enum
Private _LayoutRoot As FrameworkElement = Nothing
Private _FlipButton As FrameworkElement = Nothing
Private _FrontContentPresenter As FrameworkElement = Nothing
Private _BackContentPresenter As FrameworkElement = Nothing
Private _ControlUpdating As Boolean = False
Public Sub New()
MyBase.New()
MyBase.DefaultStyleKey = GetType(FlipPanel)
End Sub
Public Overrides Sub OnApplyTemplate()
MyBase.OnApplyTemplate()
UpdateControl()
End Sub
Private Sub UpdateControl()
If _ControlUpdating Then Exit Sub
_ControlUpdating = True
If _LayoutRoot Is Nothing Then _LayoutRoot = TryCast(GetTemplateChild(LayoutRoot_ElementName), FrameworkElement)
If _LayoutRoot IsNot Nothing Then
Dim element As Grid = TryCast(_LayoutRoot, Grid)
If element IsNot Nothing Then
' Update LayoutGrid here.
End If
End If
If _FlipButton Is Nothing Then _FlipButton = TryCast(GetTemplateChild(FlipButton_ElementName), FrameworkElement)
If _FlipButton IsNot Nothing Then
Dim element As Button = TryCast(_FlipButton, Button)
If element IsNot Nothing Then
' Update Button
RemoveHandler element.Click, AddressOf _FlipButton_Click
AddHandler element.Click, AddressOf _FlipButton_Click
End If
End If
If _FrontContentPresenter Is Nothing Then _FrontContentPresenter = TryCast(GetTemplateChild(FrontContentPresenter_ElementName), FrameworkElement)
If _FrontContentPresenter IsNot Nothing Then
Dim element As ContentPresenter = TryCast(_FrontContentPresenter, ContentPresenter)
If element IsNot Nothing Then
' Update FrontContentPresenter here.
If Side = Sides.Front Then
element.Visibility = Windows.Visibility.Visible
Else
element.Visibility = Windows.Visibility.Collapsed
End If
End If
End If
If _BackContentPresenter Is Nothing Then _BackContentPresenter = TryCast(GetTemplateChild(BackContentPresenter_ElementName), FrameworkElement)
If _BackContentPresenter IsNot Nothing Then
Dim element As ContentPresenter = TryCast(_BackContentPresenter, ContentPresenter)
If element IsNot Nothing Then
' Update BackContentPresenter here.
If Side = Sides.Front Then
element.Visibility = Windows.Visibility.Collapsed
Else
element.Visibility = Windows.Visibility.Visible
End If
End If
End If
_ControlUpdating = False
End Sub
Private Sub _FlipButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Select Case Side
Case Sides.Front
Side = Sides.Back
Case Sides.Back
Side = Sides.Front
Case Else
Throw New ArgumentOutOfRangeException("Side")
End Select
UpdateControl()
End Sub
Private Sub FlipPanel_LayoutUpdated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.LayoutUpdated
UpdateControl()
End Sub
#Region " FrontDataTemplateProperty Dependency Property "
#Region " FrontDataTemplate Property "
Public Property FrontDataTemplate() As DataTemplate
Get
Return DirectCast(GetValue(FrontDataTemplateProperty), DataTemplate)
End Get
Set(ByVal value As DataTemplate)
SetValue(FrontDataTemplateProperty, value)
End Set
End Property
#End Region
#Region " FrontDataTemplate Dependency Property "
Public Shared ReadOnly FrontDataTemplateProperty As DependencyProperty = DependencyProperty.Register("FrontDataTemplate", GetType(DataTemplate), GetType(FlipPanel), New PropertyMetadata(Nothing, AddressOf OnFrontDataTemplatePropertyChanged))
#End Region
#Region " FrontDataTemplate Property Changed CallBack "
Private Shared Sub OnFrontDataTemplatePropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
If e.OldValue Is Nothing AndAlso e.NewValue Is Nothing Then Exit Sub
If e.OldValue IsNot Nothing AndAlso e.OldValue.Equals(e.NewValue) Then Exit Sub
Dim source As FlipPanel = TryCast(d, FlipPanel)
If source Is Nothing Then Throw New ArgumentException("source is not an instance of FlipPanel!")
' Provide any other validation here.
' Apply any other changes here.
End Sub
#End Region
#End Region
#Region " BackDataTemplateProperty Dependency Property "
#Region " BackDataTemplate Property "
Public Property BackDataTemplate() As DataTemplate
Get
Return DirectCast(GetValue(BackDataTemplateProperty), DataTemplate)
End Get
Set(ByVal value As DataTemplate)
SetValue(BackDataTemplateProperty, value)
End Set
End Property
#End Region
#Region " BackDataTemplate Dependency Property "
Public Shared ReadOnly BackDataTemplateProperty As DependencyProperty = DependencyProperty.Register("BackDataTemplate", GetType(DataTemplate), GetType(FlipPanel), New PropertyMetadata(Nothing, AddressOf OnBackDataTemplatePropertyChanged))
#End Region
#Region " BackDataTemplate Property Changed CallBack "
Private Shared Sub OnBackDataTemplatePropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
If e.OldValue Is Nothing AndAlso e.NewValue Is Nothing Then Exit Sub
If e.OldValue IsNot Nothing AndAlso e.OldValue.Equals(e.NewValue) Then Exit Sub
Dim source As FlipPanel = TryCast(d, FlipPanel)
If source Is Nothing Then Throw New ArgumentException("source is not an instance of FlipPanel!")
' Provide any other validation here.
' Apply any other changes here.
End Sub
#End Region
#End Region
#Region " SideProperty Dependency Property "
#Region " Side Property "
Public Property Side() As Sides
Get
Return DirectCast(GetValue(SideProperty), Sides)
End Get
Set(ByVal value As Sides)
SetValue(SideProperty, value)
End Set
End Property
#End Region
#Region " Side Dependency Property "
Public Shared ReadOnly SideProperty As DependencyProperty = DependencyProperty.Register("Side", GetType(Sides), GetType(FlipPanel), New PropertyMetadata(Sides.Front, AddressOf OnSidePropertyChanged))
#End Region
#Region " Side Property Changed CallBack "
Private Shared Sub OnSidePropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
If e.OldValue Is Nothing AndAlso e.NewValue Is Nothing Then Exit Sub
If e.OldValue IsNot Nothing AndAlso e.OldValue.Equals(e.NewValue) Then Exit Sub
Dim source As FlipPanel = TryCast(d, FlipPanel)
If source Is Nothing Then Throw New ArgumentException("source is not an instance of FlipPanel!")
' Provide any other validation here.
' Apply any other changes here.
End Sub
#End Region
#End Region
End Class
Now, what you've been waiting for, the code!
Enjoy!
Google Code - http://code.google.com/p/stackoverflow-answers-by-scott/
Google Code - Source Code (Zip)
Thank you!