我有一个单词addin,它有一个 WPF 自定义任务窗格。我有一个Listview
。当word文档向下滚动时,我需要动态更新每个listview
项的位置。但其中一些可能具有相同的canvas.top(vertical Y)
值。然后这些项重叠。
我不需要重叠那些,我需要列表视图需要一个接一个地对齐。
代码示例XAML ..
<listViewTool:ListView x:Name="Results" Margin="0" BorderThickness="0" DockPanel.Dock="Top" Background="WhiteSmoke"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Results}"
SelectionMode="Single">
<listViewTool:ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Control.HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Control.Margin" Value="0"/>
<Setter Property="Control.Padding" Value="0"/>
<Setter Property="Control.BorderThickness" Value="0"/>
<Setter Property="IsSelected" Value="{Binding Path=Selected, Mode=TwoWay}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
<Setter Property="Canvas.Left" Value="0"/>
<Setter Property="Canvas.Width" Value="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListView}},Path=ActualWidth}" />
</Style>
</listViewTool:ListView.ItemContainerStyle>
<listViewTool:ListView.ItemsPanel>
<ItemsPanelTemplate>
<Canvas x:Name="CanvasMain" HorizontalAlignment="Stretch" Height="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListView}},Path=ActuaHeight}"
ClipToBounds="True" />
</ItemsPanelTemplate>
</listViewTool:ListView.ItemsPanel>
</listViewTool:ListView>
感谢。
答案 0 :(得分:1)
我做了一个简单的解决方案,看起来像这样:
想法是存储物品的高度,并在高度改变时重新计算所有物品的位置。
项目高度为项目模板边框ActualHeight
。对于每个项目:Y
是初始位置,Offset
计算/用于绑定(基于当前项目之前的项目的Height
)。
解决方案包含一些调试代码(Text
属性和绑定)并且不是纯MVVM(但你没有要求):
XAML:
<ListView ItemsSource="{Binding Items}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Canvas.Left"
Value="0" />
<Setter Property="Canvas.Top"
Value="{Binding Offset}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border CornerRadius="10"
BorderThickness="1"
BorderBrush="Gray"
SizeChanged="Border_SizeChanged">
<Expander Header="{Binding Text}">
<Grid Height="50" />
</Expander>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Height="{Binding ActualHeight, RelativeSource={RelativeSource FindAncestor, AncestorType=ListView}}"
ClipToBounds="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListView>
CS:
public class Item : INotifyPropertyChanged
{
// INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string property = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
public double Y { get; set; }
public double Height { get; set; }
double _offset;
public double Offset
{
get { return _offset; }
set
{
_offset = value;
OnPropertyChanged();
OnPropertyChanged(nameof(Text));
}
}
public string Text => $"Y={Y} Height={Height} Offset={Offset}";
}
public partial class MainWindow : Window
{
public ObservableCollection<Item> Items { get; } = new ObservableCollection<Item>();
public MainWindow()
{
InitializeComponent();
for (int i = 0; i < 10; i++)
Items.Add(new Item { Y = i * 40 });
DataContext = this;
}
void Border_SizeChanged(object sender, SizeChangedEventArgs e)
{
var border = (Border)sender;
var current = (Item)border.DataContext;
current.Height = border.ActualHeight;
// recalculate offset
var y = Items[0].Y;
foreach (var item in Items)
{
item.Offset = y > item.Y ? y : item.Y;
y = item.Offset + item.Height;
}
}
}