我想将元素添加到StackPanel(或Listbox / Listview,如果它会使这更容易)并自动添加一个Button(如“...”),以表明有更多的孩子,而不是有空间。 考虑每天都有约会项目的日历。如果预约的次数多于可显示的次数,则会显示一个按钮,以显示当天的详细视图。
可以自动完成,或者如何计算堆叠面板及其项目的位置。
用于c#中的windows store开发。
答案 0 :(得分:0)
您可以使用行为(需要System.Windows.Interactivity
参考)。
我抓住你的想法计算堆叠面板及其子框架的高度(或堆叠面板具有水平方向的宽度),如果有必要则显示“更多项目”/详细信息按钮
public class ChildSpaceBehavior : Behavior<StackPanel>
{
public static readonly DependencyProperty ShowDetailsCommandProperty = DependencyProperty.Register("ShowDetailsCommand", typeof(RelayCommand), typeof(ChildSpaceBehavior), new PropertyMetadata());
public RelayCommand ShowDetailsCommand
{
get { return (RelayCommand)GetValue(ShowDetailsCommandProperty); }
set { SetValue(ShowDetailsCommandProperty, value); }
}
private bool _isMoreChildrenItemVisible;
protected override void OnAttached()
{
AssociatedObject.LayoutUpdated += OnLayoutUpdated;
}
protected override void OnDetaching()
{
AssociatedObject.LayoutUpdated -= OnLayoutUpdated;
}
private void OnLayoutUpdated(object sender, EventArgs e)
{
var height = AssociatedObject.Height;
var children = AssociatedObject.Children;
double childHeighSum = 0;
var childList = new List<FrameworkElement>();
foreach (FrameworkElement child in children)
{
if (childHeighSum > height)
{
ShowMoreChildrenItem(childList);
break;
}
if (childHeighSum + child.ActualHeight > height)
{
ShowMoreChildrenItem(childList);
break;
}
childHeighSum += child.ActualHeight;
childList.Add(child);
}
}
private void ShowMoreChildrenItem(List<FrameworkElement> childList)
{
if (_isMoreChildrenItemVisible) return;
var moreItem = new Button{ Content = "..." };
moreItem.Command = ShowDetailsCommand;
var itemsToRemove = new List<FrameworkElement>();
foreach (FrameworkElement child in AssociatedObject.Children)
{
if(childList.Contains(child) == false) itemsToRemove.Add(child);
}
foreach (var element in itemsToRemove)
{
AssociatedObject.Children.Remove(element);
}
AssociatedObject.Children.Add(moreItem);
_isMoreChildrenItemVisible = true;
}
}
对于RelayCommand,请查看here
的Xaml:
<Grid>
<StackPanel Height="200" Orientation="Vertical">
<Border BorderBrush="Gray" BorderThickness="1">
<Label Height="50" Content="Item 1" />
</Border>
<Border BorderBrush="Gray" BorderThickness="1">
<Label Height="50" Content="Item 2" />
</Border>
<Border BorderBrush="Gray" BorderThickness="1">
<Label Height="50" Content="Item 3" />
</Border>
<Border BorderBrush="Gray" BorderThickness="1">
<Label Height="50" Content="Item 4" />
</Border>
<Border BorderBrush="Gray" BorderThickness="1">
<Label Height="50" Content="Item 5" />
</Border>
<i:Interaction.Behaviors>
<StackPanelBehavior:ChildSpaceBehavior ShowDetailsCommand="{Binding ShowDetailsCommand}" />
</i:Interaction.Behaviors>
</StackPanel>
</Grid>
答案 1 :(得分:0)
由于我的页面几乎所有元素都是自动调整大小,因此对上述解决方案的以下更改有所帮助。 包含stackpanels网格的页面:
public MainPage()
{
InitializeComponent();
}
private void FillGridWithItems()
{
//Row and ColumnDefinitions
for (int row = 0; row < 5; row++)
{
for (int col = 0; col < 7; col++)
{
var item = new MyStackPanel(children)
Grid.SetColumn(item, col);
Grid.SetRow(item, row);
grid.Children.Add(item);
}
}
Loaded+=PageLoaded;
}
/// When page is loaded, ActualHeight of elements are calculated for sure.
private void PageLoaded(object sender, RoutedEventArgs e)
{
foreach (var child in grid.Children)
{
var item = child as MyStackPanel;
if (item != null)
{
item.FillInData();
}
}
}
/// Used instead of constructor, cause a parameter is sent to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
FillGridWithItems()
}
MyStackPanel:
private readonly List<string> _items;
public MyStackPanel(List<string> items)
{
_items = items;
var behavior = new MyBehavior();
behavior.SetBinding(MyBehavior.ShowDetailsCommandProperty, new Binding
{
Path = new PropertyPath("ShowDetailsCommand")
});
Interaction.GetBehaviors(this).Add(behavior);
}
public void FillInData()
{
foreach (string item in _items)
{
var block = new Button();
block.Click += ItemClick;
this.Children.Add(block);
}
}
MyBehaviour(只是改变的部分)
...
private void OnLayoutUpdated(object sender, object o)
{
var container = (Grid) AssociatedObject.Parent;
if (container == null) return;
var height = container.RowDefinitions[Grid.GetRow(AssociatedObject)].ActualHeight;
// ... The same as above
}
....
我还没有实现ShowDetailsCommand,所以我不能说RelayCommand是否按预期工作,但为什么不能;) 还有一些需要对Windows商店进行的修改,比如使用WinRtBehaviors库,这些都可以通过谷歌搜索来解决。