Крис,
Я не знаю, если вы все еще ищете способ сделать это. Я знаю, что есть много руководств по подобным проблемам, но не совсем то, что вы ищете. Исходя из моего понимания того, что вы хотите, вам нужен элемент управления с двумя гранями (действительно x гранями), где пользователь может нажать кнопку и заставить панель «перевернуться» и отобразить разные данные. Однако вы хотите, чтобы эти данные были достаточно общими, чтобы эту панель можно было использовать в других местах с другой реализацией, а не с совершенно другим кодом. Я правильно понимаю ваши потребности? Если нет, пожалуйста, уточните, где я сбился с пути, и, возможно, я смогу получить лучший ответ для вас. Учитывая сказанное, вот что я сделал (демонстрационный проект Google Code внизу):
- Я создал библиотеку элементов управления, в которой хранится моя FlipPanel (потому что именно так я и поступаю; чтобы в дальнейшем я мог использовать элементы управления в других проектах.)
- Я создал элемент управления в библиотеке элементов управления, чтобы он содержал описанные выше свойства, необходимые для вашего сценария.
- Я создал приложение Silverlight 2.0 для создания экземпляра элемента управления.
- Я создал базовый объект для привязки, который имеет несколько свойств, чтобы я мог продемонстрировать потенциал элемента управления.
Вот возможное определение для использования на странице Silverlight 2.0:
<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>
Альтернативой этому является определение шаблонов данных в пользовательском элементе управления (уровень страницы или даже уровень приложения) следующим образом:
Чтобы у вас было представление о том, как выглядит мой объект привязки, вот это определение (да, это VB ... Извините!):
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
В моем коде ниже приведено определение моей страницы и настройка контекста данных для откидной панели:
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
Так что, учитывая все это перед вами, мы ожидаем, что элемент управления будет отображать кнопку (в стиле элемента управления) и текстовый блок (фактически два) с надписью "Front: Это передняя часть" кнопка нажата, она «перевернута» для отображения «Назад: Это задняя часть».
С учетом всего вышесказанного, вот стиль, который я использовал для управления:
<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>
И, наконец, определение элемента управления (Осторожно - это долго):
<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
<ч />
Теперь, что вы ждали, код!
Наслаждайтесь!
Google Code - http://code.google.com/p/stackoverflow-answers-by-scott/
Google Code - Исходный код (Zip)
Спасибо!