当StackPanel父级调整大小时,更改StackPanel的子级

时间:2014-08-22 09:13:32

标签: c# wpf xaml

我在网格中有一些StackPanel个。它们填充有标签(所有标签的高度和可显示空间)。可能的XAML是:

<Grid>
  <StackPanel>
    <Label Content="bla" Background="lime" />
    <Label ...>
    ...
  </StackPanel>
</Grid>

每次Grid的大小发生变化时,我都需要更改StackPanel的内部内容。我需要隐藏仅部分显示的溢出Label。为此,我可以使用以下解决方案:with a Convertermake a new class that is inherited from StackPanel

我想通过使用附加属性创建一种不同的方式。我有以下代码:

//DepProp OverflowVisibility (double), can save height value

public static void Initialized(DependencyObject pObject, DependencyPropertyChangedEventArgs e)
{
  var panel = (pObject as Panel) //the StackPanel in this case
  panel.SizeChanged += panel_updateInnerLayout;
}

static void panel_LayoutUpdated(object sender, EventArgs e)
{
  var parent = sender as Panel;

  if(parent != null)
    foreach(FrameworkElement element in parent.Children)
    {
      var elementPos = element.TransformToAncestor(parent).Transform(new Point(0,0));

      if(element.ActualHeight + elementPos.Y >
        (double)parent.GetValue(OverflowVisibilityProperty))
        element.Visibility = Visibility.Hidden;
      else
        element.Visibility = Visibility.Visible;
    }
}

以及在XAML中使用的示例:

<Grid>
  <ItemsControl>
    <ItemsPanel>
      <ItemsPanelTemplate>
        <StackPanel own:OverflowVisibility.OverflowVisibility="{Binding Grid height}" />
      </ItemsPanelTemplate>
    </ItemsPanel>
  </ItemsControl>
</Grid>

每次StackPanel更改大小时,我都可以使用panel_updateInnerLayout事件处理程序更新我的标签。当StackPanel的大小发生变化时,一切正常。

我的问题:StackPanel本身并不会引发SizeChanged,因为它的高度高于Grid。每当Grid改变其高度时,我都需要一个提升的事件。

我的问题:是否有任何事件而非SizeChanged,每次更改Grid尺寸时都会调用此事件?如果没有,是否有另一种附加属性来解决我的问题呢?

我还尝试设置StackPanelItemsControl ActualHeight高度的绑定,但它不会提升SizeChanged

2 个答案:

答案 0 :(得分:1)

不幸的是,您选择了错误的Panel控件来满足您的要求。 StackPanel只应在其内容的大小调整时使用,因为它不提供任何子控件调整大小的能力。因此,您应该使用提供调整大小功能的Grid或任何其他Panel。有关选择相应Panel的更多帮助,请参阅MSDN上的Panels Overview页面。

答案 1 :(得分:0)

有两种可能的事件:SizeChangedLayoutUpdatedSizeChanged无法正常工作,因为StackPanel未调整大小。 LayoutUpdated不起作用,因为此事件的sender始终为null,我无法找到StackPanel的来源。

有关详情,请参阅:Layout Events - SizeChanged and LayoutUpdated

所以我的方法没有可能的事件。

当我搜索解决方案时,我也发现,我还使用附加属性一词来表示附加行为混合行为 。区别在于here。摘要:属性对对象不执行任何操作,但可以使用它们的存在,行为会更改对象行为。混合行为是Microsoft为Microsoft Blend创建的行为。我的问题中的代码是附加行为

对于附加行为我没有找到解决方案,但对于 Blend行为,我发现了一些。您需要添加引用Micosoft.Windows.Interactivity

之后我使用了这段代码:

public class OverflowVisibilityBehavior : Behavior<VirtualizingStackPanel>
{
  protected override void OnAttached()
  {
    AssociatedObject.LayoutUpdated += AssociatedObject_LayoutUpdated;
    base.OnAttached();
  }

  protected override void OnDetaching()
  {
    AssociatedObject.LayoutUpdated -= AssociatedObject_LayoutUpdated;
  }

  void AssociatedObject_LayoutUpdated(object sender, EventArgs e)
  {
    var parent = AssociatedObject; //that solves the problem: you can get a "sender" information

    //...
    // Instead of property GetValue
    (VisualTreeHelper.GetParent(parent) as ItemsPresenter).ActualHeight
  }
}

还剩下一些问题:StackPanel的父级必须引发SizeChanged。如果您在StackPanelStackPanelGrid,则需要对其进行修改。

第二:LayoutUpdated多次更改StackPanel。比我需要的次数多。