如何重新控制在WPF中具有特定的UI

时间:2013-08-13 11:04:00

标签: wpf wpf-controls

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

enter image description here

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

更新

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:2)

据我所知,你需要添加Up,Down,它会用图像滚动ListBoxListBox已包含带有标准滚动条的ScrollViewer。我建议我们应该隐藏标准滚动条,并使用导航按钮设置自己。

这些按钮的功能将参考标准ScrollViewer。要访问ScrollViewer中的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。下面是一个带注释的完整示例。

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

enter image description here

<强> 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

enter image description here

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

我认为这种方法不是百分之百。如果速度很重要,或者大量图像,则需要优化方法,或者提出另一种方法。

<强> 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

enter image description here