这里我给出了一个控件的图像,它将显示许多图像的缩略图,并且用户可以在图像之间滚动。用户可以设置每行显示多少图像。用户可以设置显示多少行并可以进行数据绑定(bind)等。
我是 WPF 新手。所以请指导我如何绘制上面那样的输出。谢谢
更新
最佳答案
据我了解,您需要添加向上、向下,这将滚动 ListBox
与图像。 ListBox
已经包含一个带有标准滚动条的 ScrollViewer
。我建议我们应该隐藏标准滚动条,并为自己设置导航按钮。
这些按钮的功能将引用标准的ScrollViewer
。为了访问 ListBox
中的 ScrollViewer
,您必须使用以下函数:
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>
隐藏代码
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;
}
}
}
输出
编辑:
要在单个 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>
图像类
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"
});
输出
如果你确实需要动态改变图像的数量,从这种情况来看,你可以这样做——设置属性所在的集合,例如仅单个图像。然后,将其清理并以任意数量的图像将其放置在设定值上。
我认为这个方法并不是百分百适合这个方法。如果速度很重要,或者图像数量很大,就需要优化方法,或者想出另一种方法。
编辑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>
输出
关于wpf - 如何重新设计控件的样式以在 WPF 中具有特定的 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18207412/