2

在这里,我给出了一个控件的图像,它将显示许多图像的缩略图,用户可以在图像之间滚动。用户可以设置每行显示多少张图像。用户可以设置将显示多少行以及可以进行数据绑定等。

在此处输入图像描述

我是 WPF 的新手。所以请指导我如何绘制上面的输出。谢谢

更新

在此处输入图像描述

在此处输入图像描述

4

1 回答 1

2

据我了解,您需要添加向上,向下,这将ListBox与图像一起滚动。ListBox已经包含一个ScrollViewer带有标准滚动条的。我建议我们应该隐藏标准滚动条,并设置导航按钮。

这些按钮的功能将参考标准ScrollViewer。为了访问ScrollViewerin ListBox,您必须使用以下功能:

public static DependencyObject GetScrollViewer(DependencyObject Object)
{
    if (Object is ScrollViewer)
    {
        return Object;
    }

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(Object); i++)
    {
        var child = VisualTreeHelper.GetChild(Object, i);
        var result = GetScrollViewer(child);

        if (result == null)
        {
            continue;
        }
        else
        {
            return result;
        }
    }

    return null;
}

VisualTreeHelper在此函数的帮助下,返回一个类型为 的对象ScrollViewer

垂直向上导航如下:

scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - 30);

我们为按钮定义了一个样式,它将包含Path箭头形式的 a。下面是一个带有注释的完整示例。

XAML

<Window x:Class="CustomListboxNavHelp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:CustomListboxNavHelp"
    Title="MainWindow" Height="450" Width="525"
    WindowStartupLocation="CenterScreen"
    ContentRendered="Window_ContentRendered">

<Window.Resources>      
    <!-- Style for ListBox -->
    <Style x:Key="MyListBoxStyle" TargetType="{x:Type ListBox}">
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="BorderBrush" Value="Transparent" />
        <Setter Property="ScrollViewer.CanContentScroll" Value="False" />
        <Setter Property="HorizontalAlignment" Value="Center" />

        <!-- Hidden Scrollbar`s -->
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />

        <!-- DataTemplate for ListBoxItem -->
        <Setter Property="ItemTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Border BorderBrush="Transparent" BorderThickness="1">
                        <Image Source="{Binding Path=MyImagePath}" Stretch="Fill" Width="100" Height="140" />
                    </Border>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- Style for UpButton -->
    <Style x:Key="UpButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="ToolTip" Value="Up" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border CornerRadius="0" Background="{TemplateBinding Background}">
                        <Grid>
                            <ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                            <Path x:Name="UpButton" SnapsToDevicePixels="True" Width="20" Height="18" Stretch="Fill" Fill="Gray" Data="F1 M 37.8516,35.625L 34.6849,38.7917L 23.6016,50.2708L 23.6016,39.9792L 37.8516,24.9375L 52.1016,39.9792L 52.1016,50.2708L 41.0182,38.7917L 37.8516,35.625 Z "/>
                        </Grid>
                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="UpButton" Property="Fill" Value="Black" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- Style for DownButton -->
    <Style x:Key="DownButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="ToolTip" Value="Down" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border CornerRadius="0" Background="{TemplateBinding Background}">
                        <Grid>
                            <ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                            <Path x:Name="DownButton" SnapsToDevicePixels="True" Width="20" Height="18" Stretch="Fill" Fill="Gray" Data="F1 M 37.8516,39.5833L 52.1016,24.9375L 52.1016,35.2292L 37.8516,50.2708L 23.6016,35.2292L 23.6016,24.9375L 37.8516,39.5833 Z "/>
                        </Grid>
                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="DownButton" Property="Fill" Value="Black" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<Grid>
    <StackPanel>
        <Button Name="UpDirection" Style="{StaticResource UpButtonStyle}" Width="40" Height="30" Click="UpDirection_Click" />

        <ListBox Name="MyListBox" Style="{StaticResource MyListBoxStyle}" Width="110" Height="300" />

        <Button Name="DownDirection" Style="{StaticResource DownButtonStyle}" Width="40" Height="30" Click="DownDirection_Click" />
    </StackPanel>
</Grid>
</Window>

Code behind

public partial class MainWindow : Window
{
    private ObservableCollection<ImagesClass> ImagesCollection = new ObservableCollection<ImagesClass>();

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_ContentRendered(object sender, EventArgs e)
    {
        ImagesCollection.Add(new ImagesClass()
        {
            MyImagePath = "Cover1.png"     // Images must be in resource
        });

        ImagesCollection.Add(new ImagesClass()
        {
            MyImagePath = "Cover2.png"
        });

        ImagesCollection.Add(new ImagesClass()
        {
            MyImagePath = "Cover3.png"
        });

        ImagesCollection.Add(new ImagesClass()
        {
            MyImagePath = "Cover4.png"
        });

        ImagesCollection.Add(new ImagesClass()
        {
            MyImagePath = "Cover5.png"
        });

        ImagesCollection.Add(new ImagesClass()
        {
            MyImagePath = "Cover6.png"
        });

        MyListBox.ItemsSource = ImagesCollection;
    }

    private void UpDirection_Click(object sender, RoutedEventArgs e)
    {
        NavigationInScrollViewer(MyListBox, "Up", 40);
    }

    private void DownDirection_Click(object sender, RoutedEventArgs e)
    {
        NavigationInScrollViewer(MyListBox, "Down", 40);
    }

    /// <summary>
    /// Vertical navigation for ListBox
    /// </summary>
    /// <param name="myListbox">ListBox</param>
    /// <param name="direction">Direction for scrolling</param>
    /// <param name="offset">Offset</param>
    private void NavigationInScrollViewer(ListBox myListbox, string direction, int offset) 
    {
        ScrollViewer scrollViewer = GetScrollViewer(MyListBox) as ScrollViewer;

        if (direction == "Up") 
        {
            if (scrollViewer != null)
            {
                scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - offset);
            }
        }

        if (direction == "Down") 
        {                
            if (scrollViewer != null)
            {
                scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + offset);
            }
        }
    }

    /// <summary>
    /// Get ScrollViewer from Control
    /// </summary>
    /// <param name="Object">Dependency object</param>
    /// <returns>ScrollViewer control</returns>
    public static DependencyObject GetScrollViewer(DependencyObject Object)
    {
        if (Object is ScrollViewer)
        {
            return Object;
        }

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(Object); i++)
        {
            var child = VisualTreeHelper.GetChild(Object, i);
            var result = GetScrollViewer(child);

            if (result == null)
            {
                continue;
            }
            else
            {
                return result;
            }
        }

        return null;
    }
}

/// <summary>
/// Class contain paths to images
/// </summary>
public class ImagesClass
{
    private string myImagePath = null;

    public string MyImagePath
    {
        get
        {
            return myImagePath;
        }

        set
        {
            myImagePath = value;
        }
    }
}

Output

在此处输入图像描述

EDIT:

要在单个图像中显示多个图像ListBoxItem,您需要进行更正ItemTemplate。我建议使用Grid, 因为它是ColumnDefenition用于定义项目列号的属性。

另一件事是您知道这是可取的:

  • 最终显示的图像数量为一张ListBoxItem

  • 对于大量图像需要改进的方法,因为它更适合静态显示。

像这样正确ItemTenplate

<Setter Property="ItemTemplate">
    <Setter.Value>
        <DataTemplate>
            <Border BorderBrush="Transparent" BorderThickness="1">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>

                    <Image Source="{Binding Path=MyImagePathOne}" Grid.Column="0" Stretch="Fill" Width="100" Height="140" />
                    <Image Source="{Binding Path=MyImagePathTwo}" Grid.Column="1" Stretch="Fill" Width="100" Height="140" />
                </Grid>
            </Border>
       </DataTemplate>
   </Setter.Value>
</Setter>

ImageClass

public class ImagesClass
{
    private string myImagePathOne = null;

    public string MyImagePathOne
    {
        get
        {
            return myImagePathOne;
        }

        set
        {
            myImagePathOne = value;
        }
    }

    private string myImagePathTwo = null;

    public string MyImagePathTwo
    {
        get
        {
            return myImagePathTwo;
        }

        set
        {
            myImagePathTwo = value;
        }
    }
}

将图像添加到集合:

ImagesCollection.Add(new ImagesClass()
{
    MyImagePathOne = "Cover1.png",
    MyImagePathTwo = "Cover2.png"
});

ImagesCollection.Add(new ImagesClass()
{
    MyImagePathOne = "Cover3.png",
    MyImagePathTwo = "Cover4.png"
});

ImagesCollection.Add(new ImagesClass()
{
    MyImagePathOne = "Cover5.png",
    MyImagePathTwo = "Cover6.png"
});

Output

在此处输入图像描述

如果您确实需要动态更改图像的数量,在这种情况下,您可以这样做 - 设置设置属性的集合,例如,只有单个图像。然后,清理它并将其放置在具有任意数量图像的设定值上。

我认为这种方法不是百分百适用于这种方法。如果速度很重要,或者图像数量很多,就要优化方法,或者想出另一种方法。

EDIT 2

向上和向下按钮:

<Button Name="Up" Width="150" Height="15" Background="#CDE2FF">
    <Button.Content>
        <Polygon Points="3.33,0 6.66,6.66, 0,6.66" Fill="#466690" />
    </Button.Content>
</Button>

<Button Name="Down" Width="150" Height="15" Background="#CDE2FF" Margin="0,10,0,0">
    <Button.Content>
        <Polygon Points="0,0 3.33,6.66, 6.66,0" Fill="#466690" />
    </Button.Content>
</Button>

Output

在此处输入图像描述

于 2013-08-14T07:43:09.277 回答