2013-12-21 167 views
0

我想防止按鈕(ButtonExpander)在單擊後在ListBox的視口之外移動,直到再次單擊它爲止。按鈕的父級必須是可見的(有足夠的空間用於按鈕),並且該按鈕不能離開它所屬的用戶控件的邊界。如果這些條件中的任何一個都不符合,則該按鈕返回到其正常行爲。任何想法如何最好地完成這個?防止元素在滾動時消失

MainWindow.xaml

<Window 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" 
     x:Name="WinMain" 
     x:Class="MainWindow" 
     Title="Window" 
     Height="500" 
     Width="680" 
     WindowStartupLocation="CenterScreen" 
     mc:Ignorable="d" 
     Margin="0" 
     MaxWidth="700"> 
    <Window.Background> 
     <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> 
      <GradientStop Color="Black"  Offset="0.27"/> 
      <GradientStop Color="#FF2E2E2E" Offset="0.105"/> 
      <GradientStop Color="#FF1D1D1D" Offset="1"/> 
      <GradientStop Color="Black"  Offset="0.91"/> 
     </LinearGradientBrush> 
    </Window.Background> 
     <Grid x:Name="GridMain"> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="35"/> 
       <RowDefinition Height="40" MaxHeight="40" MinHeight="40"/> 
       <RowDefinition/> 
       <RowDefinition Height="34" MinHeight="34" MaxHeight="34"/> 
      </Grid.RowDefinitions> 
     <Rectangle x:Name="Menu"  Grid.Row="0" Fill="#FF5F5F5F"/> 
     <Rectangle x:Name="SomeButtons" Grid.Row="1" Fill="#FF303243"/> 
     <ListBox x:Name="LbFancy" 
       Margin="10" 
       Grid.Row="2" 
       ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
       ScrollViewer.VerticalScrollBarVisibility="Auto" 
       ScrollViewer.CanContentScroll="False" 
       Focusable="False" 
       VerticalAlignment="Center" 
       HorizontalAlignment="Center"> 
      <ListBox.Resources> 
       <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}">#00000000</SolidColorBrush> 
      </ListBox.Resources> 
     </ListBox> 
     <Rectangle x:Name="Status" Grid.Row="3" Fill="#FF303243"/> 
    </Grid> 
</Window> 

MainWindow.vb

Class MainWindow 
    Dim CurrentMapArray() As String = {"01_FooBar", "02_BarFoo", "03_OofRab", "04_Rab_Oof", "07_Santa", "08_Cat"} 
    Public Sub New() 
     'This call is required by the designer 
     InitializeComponent() 
    End Sub 
    Private Sub Build() 
     'All Maps item 
     Dim mapinfodef As MapInfo = New MapInfo 
     LbFancy.Items.Add(mapinfodef) 
     LbFancy.Items.GetItemAt(0) 
     mapinfodef.MapTitleInternal.Text = "" 
     mapinfodef.MapTitle.Text = "All Maps" 
     For Each map As String In CurrentMapArray 
      Dim mapinfotemp As MapInfo = New MapInfo 
      'Set basic values for element properties, etc 
      LbFancy.Items.Add(mapinfotemp) 
     Next 
    End Sub 
    Private Sub Main() Handles WinMain.Loaded 
     Build() 
    End Sub 
End Class 

列表框被通過代碼填入身後數十以下用戶控制的副本:

MapInfo.xaml

<UserControl 
    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" 
    x:Class="MapInfo" 
    x:Name="Mapinfo" 
    Margin="0,2,3,0" 
    MinWidth="600" 
    MinHeight="77"> 
    <Grid x:Name="GridRoot" Height="77" Background="Black"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="563"/> 
      <ColumnDefinition Width="Auto"/> 
     </Grid.ColumnDefinitions> 
     <Grid x:Name="MapCanvas"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition MinWidth="112" Width="Auto"/> 
       <ColumnDefinition MinWidth="451" Width="451"/> 
       <ColumnDefinition MinWidth="36" MaxWidth="36"/> 
      </Grid.ColumnDefinitions> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="25" MaxHeight="25"/> 
       <RowDefinition Height="25" MaxHeight="25"/> 
       <RowDefinition Height="25" MaxHeight="25"/> 
       <RowDefinition/> 
       <RowDefinition/> 
      </Grid.RowDefinitions> 
      <Border Height="62" 
        Width="102" 
        Grid.Row="0" 
        Grid.RowSpan="3" 
        Grid.Column="0" 
        BorderBrush="White" 
        Margin="5,6,0,6" 
        HorizontalAlignment="Left" 
        VerticalAlignment="Center" 
        CornerRadius="1" 
        BorderThickness="1"> 
      </Border> 
      <TextBlock x:Name="MapTitle" 
         Text="Map Title" 
         Grid.Column="1" 
         HorizontalAlignment="Left" 
         VerticalAlignment="Center" 
         Foreground="White" 
         Margin="10,0.725,0,0.725" 
         FontSize="36" 
         Grid.Row="0" 
         Grid.RowSpan="2" 
         Panel.ZIndex="2"/> 
      <TextBlock x:Name="MapTitleInternal" 
         Text="##_MapTitle" 
         Grid.Row="2" 
         Grid.Column="1" 
         HorizontalAlignment="Left" 
         VerticalAlignment="Center" 
         Foreground="White" 
         Margin="10,4.354,0,4.353" 
         Panel.ZIndex="1"/> 
      <Grid x:Name="MapInfoExt" 
        Grid.Row="3" 
        Grid.RowSpan="2" 
        Grid.ColumnSpan="2" 
        Width="559" 
        Panel.ZIndex="2"> 
       <Grid.Background> 
        <SolidColorBrush Color="#00000000" Opacity="0"/> 
       </Grid.Background> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto"/> 
        <RowDefinition Height="Auto"/> 
        <RowDefinition Height="Auto"/> 
       </Grid.RowDefinitions> 
       <Rectangle x:Name="Item1" Grid.Row="0" Height="100" Fill="Red" Opacity="0.15"/> 
       <Rectangle x:Name="Item2" Grid.Row="1" Height="201" Fill="Green" Opacity="0.15"/> 
       <Rectangle x:Name="Item3" Grid.Row="2" Height="182" Fill="Blue" Opacity="0.15"/> 
      </Grid> 
     </Grid> 
     <Grid x:Name="MapPanel" 
       Margin="0,1,1,0" 
       MinHeight="73" 
       MinWidth="35" 
       MaxWidth="35" 
       Grid.Column="1" 
       Panel.ZIndex="1"> 
      <Grid.Background> 
       <LinearGradientBrush EndPoint="1,0" StartPoint="0,0"> 
        <GradientStop Color="Black"  Offset="1"/> 
        <GradientStop Color="#FF5F5F5F" Offset="0.5"/> 
        <GradientStop Color="Black"/> 
       </LinearGradientBrush> 
      </Grid.Background> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="Auto" MaxHeight="30" MinHeight="30"/> 
       <RowDefinition Height="Auto" MaxHeight="8" MinHeight="8"/> 
       <RowDefinition/> 
      </Grid.RowDefinitions> 
      <CheckBox VerticalAlignment="Top" 
         Panel.ZIndex="1" 
         Grid.Row="0" 
         BorderThickness="0.5" 
         Margin="0,9,0,0" 
         HorizontalAlignment="Center"/> 
      <Rectangle Stroke="Black" 
         Panel.ZIndex="2" 
         Grid.Row="0" 
         Margin="0,-1,0,1" 
         Grid.RowSpan="3"/> 
      <Button x:Name="ButtonExpander" 
        Panel.ZIndex="1" 
        Click="ButtonExpand_Click" 
        Grid.Row="2" 
        VerticalAlignment="Bottom" 
        Height="24" 
        Width="24" 
        VerticalAlignment="Top" 
        Margin="5"/> 
     </Grid> 
     <Border x:Name="MapBorder" 
       BorderThickness="1" 
       BorderBrush="#FF0E363C" 
       UseLayoutRounding="False" 
       RenderTransformOrigin="0.5,0.5" 
       Grid.ColumnSpan="2" 
       Grid.Column="0" 
       Grid.RowSpan="2" 
       Margin="0" 
       Panel.ZIndex="1"/> 
    </Grid> 
</UserControl> 

MapInfo.vb

Imports System.Windows.Controls 

Public Class MapInfo 
    Inherits UserControl 
    Dim _expanded As Boolean = False 

    Private Sub ButtonExpand_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) 
     If _expanded = True Then 
      _expanded = False 
      GridRoot.Height = 77 
      MapBorder.Tag = "" 
      Dim rotateTransform1 As New RotateTransform(0) 
      rotateTransform1.CenterX = 12 
      rotateTransform1.CenterY = 12 
      ButtonExpander.RenderTransform = rotateTransform1 
      Return 
     Else 
      _expanded = True 
      GridRoot.Height = 1545 
      MapBorder.Tag = "Expanded" 
      Dim rotateTransform1 As New RotateTransform(180) 
      rotateTransform1.CenterX = 12 
      rotateTransform1.CenterY = 12 
      ButtonExpander.RenderTransform = rotateTransform1 
      Return 
     End If 
    End Sub 
End Class 

點擊時ButtonExpander設置GridRoot的高度。網格可以變得非常大,所以在點擊按鈕之後,我想讓它在ListBox中保持可見,並在窗口右側的灰色區域上下滑動。基本上與本網頁右側的黃色框(類似問題,格式化幫助等)相同,或者像this(社交小部件薄)這樣的jQuery插件。

我能找到的與C#/ VB.NET唯一相似的問題是this one,但答案並沒有真正的幫助 - 一個是WinPhone,我無法查看任何代碼,另一個答案是一個scrollviewer,但我不知道如何去與ListBox做這件事。

我將不勝感激任何幫助,我將不勝感激。

回答

1

根據您的擴​​展描述,沒有優雅的方式來做到這一點。解決方案將使您關閉如下。

在MapInfo控件xaml中,從當前位置移除該按鈕,並添加一個帶有按鈕的畫布到GridRoot的末尾,如下所示。

<Border x:Name="MapBorder" BorderThickness="1" BorderBrush="#FF0E363C" UseLayoutRounding="False" RenderTransformOrigin="0.5,0.5" Grid.ColumnSpan="2" Grid.Column="0" Grid.RowSpan="2" Margin="0" Panel.ZIndex="1" /> 
<Canvas Grid.ColumnSpan="2" Background="Transparent" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Panel.ZIndex="1"> 
    <Button x:Name="ButtonExpander" Panel.ZIndex="1" Click="ButtonExpand_Click" Height="24" Width="24" Margin="5" Canvas.Right="10" Canvas.Top="24" /> 
</Canvas> 

這將允許您將按鈕定位在MapInfo控件中。

在主窗口XAML,使用像

Private Sub ScrollViewer_OnScrollChanged(ByVal sender As Object, ByVal e As ScrollChangedEventArgs) 

    For Each item As MapInfo In LbFancy.Items 
     If (item.Expanded) Then 

      Dim positionTransform = item.TransformToAncestor(LbFancy) 
      Dim itemPosition = positionTransform.Transform(New Point(0, 0)) 

      If ((itemPosition.Y > 0) And (itemPosition.Y < e.ViewportHeight)) Then 
       ' The top of the item is visible 
      ElseIf ((itemPosition.Y < 0) And (itemPosition.Y + item.ActualHeight - button.Height > 0)) Then 
       ' the top of the item is not visible but a part of the item is 
       Dim button = CType(item.FindName("ButtonExpander"), Button) 
       Canvas.SetTop(button, 0 - itemPosition.Y) 
      End If 
     End If 
    Next 

End Sub 

代碼有一個處理ScrollView.ScrollChanged事件

<ListBox x:Name="LbFancy" 
     Margin="10" 
     Grid.Row="2" 
     ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
     ScrollViewer.VerticalScrollBarVisibility="Auto" 
     ScrollViewer.CanContentScroll="False" 
     ScrollViewer.ScrollChanged="ScrollViewer_OnScrollChanged" 
     Focusable="False" 
     VerticalAlignment="Center" 
     HorizontalAlignment="Center"> 

然後在ScrollViewer_OnScrollChanged事件處理程序,管理按鈕的位置在控制範圍內在控件創建和滾動過程中都要圍繞按鈕的位置做更多的事情,但這應該讓你開始。

注:爲簡潔起見,異常處理和空檢查已被刪除。

我希望這會有所幫助。

+0

另一件事。我會考慮使用MVVM模式。您的CInfo用戶控件將成爲模型類和DataTemplate。模型類將存在於綁定到ListBox的ItemsSource的ViewModel上的ObservableCollection中,DataTemplate將分配給ListBox的ItemsTemplate屬性。這將有助於將您的用戶界面與數據分開。我已經添加了這個評論,給你一些關於MVVM的WPF DataBinding的流行詞彙。 –

+0

是的,基本上按鈕停留在列表框的視口(?)內,但有一些條件:按鈕的父項必須可見(具有足夠的按鈕空間),並且該按鈕不能離開它所屬的用戶控件的邊界至。如果這些條件中的任何一個都不符合,則該按鈕返回到其正常行爲。我用更多的信息更新了這個問題,並希望更清楚地描述我正在努力完成的任務。如果有幫助,我可以添加一些截圖嗎? MVVM的東西是我試圖學習的東西,但一次一件事。 :] – ronald

+0

修改答案以考慮修改後的問題。我希望它有幫助。 –

相關問題