滚动时防止元素消失

时间:2013-12-21 03:10:04

标签: c# wpf vb.net .net-4.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

ListBox通过后面的代码填充以下用户控件的几十个副本:

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中保持可见,并向上/向下滑动窗口右侧的灰色区域。基本上与本网页右侧的黄色框(类似问题,格式化帮助等)或jQuery插件(如this(社交窗口小部件)相同的交易。

我能找到的与C#/ VB.NET相关的唯一类似问题是this one,但答案并没有真正帮助 - 一个用于WinPhone,我无法查看任何代码,另一个答案是滚动查看器,但我不知道如何使用ListBox。

我会感激任何帮助,不一定要花哨。

1 个答案:

答案 0 :(得分: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控件中。

在MainWindow xaml中,处理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事件处理程序中,使用

等代码管理控件中按钮的位置
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

在控件创建和滚动过程中,按钮的定位还有很多工作要做,但这应该可以让你开始。

注意:为简洁起见,已删除异常处理和空检查。

我希望这会有所帮助。