|
|
1
LittleBit
6 年前
我的方法是使用带有一些修改的
-
listview的
itemspanel
必须具有“wrap”功能,因此我使用了a
wrappanel
来在字段中显示图像预览。
-
-
listViewItem的
itemcontainer
必须有两种状态。图像预览状态和详细信息视图。
expander
should do the trick.
-
-
图像的详细信息必须显示在图像下的整个列中。我们需要在
listViewItem的边界之外呈现的内容
现在看起来像这样
由于边界问题,图像细节现在变得一团糟。
height
没问题,因为它只是向下移动下一列,直到适合它。问题在于
width=>code>及其位置(其未左对齐)。
我创建了一个小的CustomControl,
StretchGrid
which渲染了整个列和左对齐的
content
此
StretchGrid
get the relative distance to the left boundary and set it as negative
Margin.Left
to render it properly.现在看起来像这样(我希望这正是你想要的)。
现在
listview的
style
<!--带细节的图像列表-->
<style x:key=“piclist”targetType=“x:type listview”>
&!--只能选择一张图片-->
<setter property=“selectionmode”value=“single”/>
&!--在项目周围使用包装板启用多行-->
<setter property=“itemspanel”>
<setter.value>
<项模板lt;itemspaneltemplate>
<wrappanel width=“绑定(listview.actualwidth),relativesource=relativesource findancestor,ancestortype=x:type listview”tag=“绑定relativesource=relativesource self”/>gt;
</itemspaneltemplate>
</setter.value>
&;
&!--覆盖项目的显示区域-->
<setter property=“itemcontainerStyle”>
<setter.value>
<style targettype=“x:type listviewitem”>
&!--定义图像项-->
<setter property=“template”>
<setter.value>
<controlTemplate targetType=“x:类型列表框项”>
&!--使用Expander标题作为预览/缩略图,展开时显示下面的详细信息-->
<expander x:name=“picThumbnail”style=“staticResource noButtonExpander”isexpanded=“绑定(listViewItem.isSelected),relativesource=relativesource findancestor,ancestorType=x:type listViewItem”width=“绑定(listViewItem.actualWidth),relativesource=relativesource findancestor,ancestortype=x:type listViewItem”>
<expander.header>
&!--缩略图/预览节-->
<堆叠面板>
<image source=“/xaml;component/assets/images/thumb.png”height=“16”width=“16”/>gt;
<label content=“绑定名称”/>
</stackpanel>
</expander.header>
&!--自动拉伸网格(自定义控件)--gt;
<cc:StretchGrid x:name=“PicDetails”background=“LightGray”parentWrappanel=“绑定路径=标记,relativesource=relativesource findancestor,ancestortype=x:type Wrappanel”>
&!--图片细节部分(快速&脏设计,稍后更换)->
<image clipTobounds=“false”source=“/xaml;组件/资产/images/highres.png”width=“128”height=“128”horizontallight=“left”margin=“10,0”/>
<rectangle fill=“black”height=“128”width=“5”horizontallight=“left”/>
<rectangle fill=“black”height=“128”width=“5”horizontallight=“right”/>
<stackpanel margin=“150,0”>
<label content=“绑定名称”/>
<label content=“说明:lorem”/>
<label content=“类别:ipsum”/>
<label content=“所有者:多尔”/>
<label content=“大小:5kb”/>
</stackpanel>
</cc:StretchGrid>
</expander>
</controltemplate>
</setter.value>
&;
&!--将所选元素置于最前面,详细信息请参见编辑-->
<style.triggers>
<trigger property=“isselected”value=“true”>
<setter property=“panel.zindex”value=“1”/>
</trigger>
</style.triggers>
&风格/风格;
</setter.value>
&;
&风格/风格;
< /代码>
注意:必须添加对StretchGrid的引用。
以及StretchGridCustom Control
class StretchGrid:grid
{
//父展开器的引用(用于计算网格边距)
专用扩展器;
//在Style中绑定到Wrappanel的RelativeSource的属性
公共Wrappanel ParentWrappanel
{
获取返回(wrappanel)this.getValue(wrappanel);
设置this.set value(wrappanel,value);
}
//RelativeSource绑定到Wrappanel的DependencyProperty(注意:绑定是在样式内部设置的,而不是在PropertyMetadata中以编程方式在此处设置的)
public static readonly dependencyproperty wrappanel=dependencyproperty.register(“parentwrappanel”,typeof(wrappanel),typeof(stretchgrid),new propertymetadata(null));
/ /构造函数
public StretchGrid():基())
{
application.current.mainwindow.loaded+=init;
application.current.mainwindow.sizechanged+=更新页边距;
}
private void init(对象发送方,routedeventargs e)
{
m_expander=(expander)this.parent;//在XAML标记层次结构更改时更改
如果(扩音器)!=空)/(或使其与包装板相似
//relativesource绑定)
m_expander.expanded+=updateMargins;//展开时更新
m_expander.sizechanged+=updateMargins;//当expander更改大小时更新
//初始化时更新所有拉伸网格
updateMargins(空,空);
}
}
//触发相应事件时计算网格边距
private void updateMargins(对象发送方,routedeventargs e)
{
如果(ParentWrappanel!=空)
{
point delta=m_expander.translatePoint(新点(0d,0d),parentWrappanel);
//创建负边距以允许在边界之外呈现网格(图像下的整列)
this.margin=新厚度(-delta.x,0,delta.x+m_expander.actualwidth-parentwrappanel.actualwidth,0);
//这些值计算不准确,只是为了举例说明,计算范围很广
}
}
}
< /代码>
在现有代码中合并有点困难。一个工作示例可能会有所帮助,并且可以找到此处。
旁注:如果我有更多的时间,我会把这些东西打包到一个更大的自定义控件中,像普通的那样使用它。这将大大提高重用性和可用性。
编辑
listView中的“new”元素也位于z索引的顶部,因此它是“above”展开的StretchGrid并且一些控件不能被单击,因为它们是“behind”the nextlistView项 。
要修复此问题,请添加
<style.triggers>
<trigger property=“isselected”value=“true”>
<setter property=“panel.zindex”value=“1”/>
</trigger>
</style.triggers>
< /代码>
到listviewitemstyle。现在,当它可见时,它会将自己放在其他控件之上。
函数,所以我用了Wrappanel 在字段中显示图像预览。
这个ItemContainter 的ListViewItem 必须有两种状态。图像预览状态和细节视图Expander 应该有技巧。
图像的详细信息必须显示在图像下的整个列中。我们需要的是一些超出列表视图项 (更晚些时候)
现在看起来像这样
由于边界问题,图像细节现在变得一团糟。这个Height 没问题,因为它只是向下移动下一列,直到它适合。问题是Width 其位置(未左对齐)。
我创建了一个小的自定义控件,StretchGrid 使其Content 穿过整列并左对齐。这个拉伸网格 获取到左边界的相对距离并将其设置为负值Margin.Left 正确渲染。现在看起来像这样(我希望这正是你想要的)。

现在Style 的列表视图
<!-- Image List with Detail -->
<Style x:Key="PicList" TargetType="{x:Type ListView}">
<!-- Only one Picture can be selected -->
<Setter Property="SelectionMode" Value="Single"/>
<!-- Enable Multi-Line with a WrapPanel Around the Items -->
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel Width="{Binding (ListView.ActualWidth),RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}}" Tag="{Binding RelativeSource={RelativeSource Self}}" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<!-- Override Display area of the Item -->
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListViewItem}">
<!-- Define Image Item -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<!-- Use Expander Header as Preview/Thumbnail and display Details below when expanded -->
<Expander x:Name="PicThumbnail" Style="{StaticResource NoButtonExpander}" IsExpanded="{Binding (ListViewItem.IsSelected), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}" Width="{Binding (ListViewItem.ActualWidth), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}">
<Expander.Header>
<!-- Thumbnail/Preview Section -->
<StackPanel>
<Image Source="/XAML;component/Assets/Images/Thumb.png" Height="16" Width="16" />
<Label Content="{Binding Name}"/>
</StackPanel>
</Expander.Header>
<!-- Self stretching Grid (Custom Control) -->
<cc:StretchGrid x:Name="PicDetails" Background="LightGray" ParentWrappanel="{Binding Path=Tag, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WrapPanel}}}">
<!-- Picture Detail Section (quick & dirty designed, replace later) -->
<Image ClipToBounds="False" Source="/XAML;component/Assets/Images/Highres.png" Width="128" Height="128" HorizontalAlignment="Left" Margin="10,0" />
<Rectangle Fill="Black" Height="128" Width="5" HorizontalAlignment="Left"/>
<Rectangle Fill="Black" Height="128" Width="5" HorizontalAlignment="Right"/>
<StackPanel Margin="150,0">
<Label Content="{Binding Name}"/>
<Label Content="Description: Lorem"/>
<Label Content="Category: Ipsum"/>
<Label Content="Owner: Dolor"/>
<Label Content="Size: 5kB"/>
</StackPanel>
</cc:StretchGrid>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
<!-- Brings selected element to front, details see edit -->
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Panel.ZIndex" Value="1" />
</Trigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
</Style>
注意:必须添加对拉伸网格 .
以及拉伸网格 自定义控件
class StretchGrid : Grid
{
//Reference for parent expander (used to calculate Grid Margin)
private Expander m_expander;
//Property for relativesource Binding to Wrappanel in Style
public WrapPanel ParentWrappanel
{
get { return (WrapPanel)this.GetValue(Wrappanel); }
set { this.SetValue(Wrappanel, value); }
}
//DependencyProperty for RelativeSource Binding to Wrappanel in Style (Note: the Binding is set inside the Style, not here programmatically in PropertyMetaData)
public static readonly DependencyProperty Wrappanel = DependencyProperty.Register("ParentWrappanel", typeof(WrapPanel), typeof(StretchGrid), new PropertyMetadata(null));
//Constructor
public StretchGrid() : base()
{
Application.Current.MainWindow.Loaded += Init;
Application.Current.MainWindow.SizeChanged += UpdateMargins;
}
private void Init(object sender, RoutedEventArgs e)
{
m_expander = (Expander)this.Parent; //Change when xaml markup hirarchy changes
if(m_expander != null) //(or make it similar to the Wrappanel with
{ //RelativeSource Binding)
m_expander.Expanded += UpdateMargins; //Update when expander is expanded
m_expander.SizeChanged += UpdateMargins; //Update when the expander changes the Size
//Update all StretchGrids on Initialization
UpdateMargins(null, null);
}
}
//Calculate Grid Margin when an according Event is triggered
private void UpdateMargins(object sender, RoutedEventArgs e)
{
if(ParentWrappanel != null)
{
Point delta = m_expander.TranslatePoint(new Point(0d, 0d), ParentWrappanel);
//Create negative Margin to allow the Grid to be rendered outside of the Boundaries (full column under the Image)
this.Margin = new Thickness(-delta.X, 0, delta.X + m_expander.ActualWidth - ParentWrappanel.ActualWidth, 0);
//Theese Values arent calculated exavtly, just broad for example purpose
}
}
}
在现有代码中合并有点困难。一个有效的例子可能会有帮助,并且可以找到HERE.
旁注:如果我有更多的时间,我会把这些东西打包到一个更大的自定义控件中,像平常一样使用它。UIElement (例如)Border )这将大大提高重用性和可用性。
编辑
中的“最新”元素列表视图 也位于z索引的顶部,因此它“高于”扩展的拉伸网格 一些控件无法单击,因为它们位于下一个控件的“后面”ListviewItem .
要修复此问题,请添加
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Panel.ZIndex" Value="1" />
</Trigger>
</Style.Triggers>
到列表视图项 风格。现在,当它可见时,它会将自己置于其他控件之上。
|