首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >绑定到项目ActualHeight的ItemsControl

绑定到项目ActualHeight的ItemsControl
EN

Stack Overflow用户
提问于 2011-02-21 00:39:25
回答 4查看 6K关注 0票数 8

我有两个单独的ItemsControl,它们并排出现。ItemsControl的绑定到相同的ItemsSource,但它们显示数据的方式不同。

左边显示的每一项都很可能比右边的同一项小。这会导致问题,因为行将不对齐,所以我需要左边的项来绑定到右侧的项。

代码语言:javascript
复制
ItemsControl        ItemsControl
|Item 1         |Item 1
|Item 2         |Item 2
|Item 3         |
|Item 4         |Item 3

正如您所看到的,右边的第2项更大,因此它抛出了对齐。所以,如果我能把左边的第二项绑定到右边的第二项的ActualHeight上,问题就解决了。我如何在XAML中做到这一点?

编辑:为了使事情变得更复杂,右边的ItemsControl需要向左滚动,但是两个ItemsControls都需要向上和向下滚动。基本上,左边的标题为右边的项提供了一个排序的标题。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-02-22 13:30:12

继续跟进Joy的回答

您不能在Xaml中为ReadOnly依赖项属性ActualHeight执行直接的ActualHeight绑定,但是有很多解决办法。肯特·布加特在this question中的回答是我最喜欢的。它所做的是使用一个附加行为,它侦听任何SizeChanged事件的FrameworkElement事件,并相应地更新两个附加属性,宽度和高度。

例如,使用TextBlock,可以使用ActualHeight推进到ViewModel的高度属性中,如

代码语言:javascript
复制
<TextBlock local:ActualSizeBehavior.ObserveActualSize="True"
           local:ActualSizeBehavior.ActualHeight="{Binding Path=Height,
                                                           Mode=OneWayToSource}"
           .../>

同步两ScrollViewers

您可以使用DependencyPropertyDescriptor侦听VerticalOffsetProperty属性中的更改,也可以订阅ScrollChanged事件并调用ScrollToVerticalOffset。示例

Xaml

代码语言:javascript
复制
<ScrollViewer Name="scrollViewerLeft"
              ScrollChanged="scrollViewerLeft_ScrollChanged">
<ScrollViewer Name="scrollViewerRight"
              ScrollChanged="scrollViewerRight_ScrollChanged">

事件处理程序背后的代码

代码语言:javascript
复制
private void scrollViewerLeft_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
    scrollViewerRight.ScrollToVerticalOffset(scrollViewerLeft.VerticalOffset);
}
private void scrollViewerRight_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
    scrollViewerLeft.ScrollToVerticalOffset(scrollViewerRight.VerticalOffset);
}

ActualSizeBehavior

代码语言:javascript
复制
public static class ActualSizeBehavior
{
    public static readonly DependencyProperty ActualSizeProperty =
        DependencyProperty.RegisterAttached("ActualSize",
                                            typeof(bool),
                                            typeof(ActualSizeBehavior),
                                            new UIPropertyMetadata(false, OnActualSizeChanged));
    public static bool GetActualSize(DependencyObject obj)
    {
        return (bool)obj.GetValue(ActualSizeProperty);
    }
    public static void SetActualSize(DependencyObject obj, bool value)
    {
        obj.SetValue(ActualSizeProperty, value);
    }
    private static void OnActualSizeChanged(DependencyObject dpo,
                                            DependencyPropertyChangedEventArgs e)
    {
        FrameworkElement element = dpo as FrameworkElement;
        if ((bool)e.NewValue == true)
        {
            element.SizeChanged += element_SizeChanged;
        }
        else
        {
            element.SizeChanged -= element_SizeChanged;
        }
    }

    static void element_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        FrameworkElement element = sender as FrameworkElement;
        SetActualWidth(element, element.ActualWidth);
        SetActualHeight(element, element.ActualHeight);
    }

    private static readonly DependencyProperty ActualWidthProperty =
        DependencyProperty.RegisterAttached("ActualWidth", typeof(double), typeof(ActualSizeBehavior));
    public static void SetActualWidth(DependencyObject element, double value)
    {
        element.SetValue(ActualWidthProperty, value);
    }
    public static double GetActualWidth(DependencyObject element)
    {
        return (double)element.GetValue(ActualWidthProperty);
    }

    private static readonly DependencyProperty ActualHeightProperty =
        DependencyProperty.RegisterAttached("ActualHeight", typeof(double), typeof(ActualSizeBehavior));
    public static void SetActualHeight(DependencyObject element, double value)
    {
        element.SetValue(ActualHeightProperty, value);
    }
    public static double GetActualHeight(DependencyObject element)
    {
        return (double)element.GetValue(ActualHeightProperty);
    }
}
票数 6
EN

Stack Overflow用户

发布于 2011-02-21 01:26:47

因为两个ItemsSource都是相同的,所以可以在单个DataTemplate中使用单个ItemsControl和整个行表示为两个部分(网格的两个列),然后高度将自动对齐。您可以始终将其样式设置为看起来像是两种不同的ItemsControl的一部分,但技术上是一种。

另一种方法是在ViewModel中添加一个with属性(当然,由于向VM中添加了View依赖项,所以设计不太正确)。TwoWay将高度绑定到左侧itemsControl ItemContainerStyle的ActualHeight。在右项控件上,将该高度属性绑定到ItemsContainerStyle {单向}的高度。所以两者是同步的。

另一个基于更新‘需要右侧滚动’的想法:使用单个ListView并在其中包含两个列,而这两个GridViewColumn.CellTemplate中有两个DataTemplates。这个想法仍然需要在第一列上冻结列。但这可能更棘手。

无论如何,我会选择第一种方法。

票数 0
EN

Stack Overflow用户

发布于 2014-12-23 17:39:59

看看我的文章:http://www.codeproject.com/KB/WPF/BindingHub.aspx

这就是如何使用BindingHub绑定到只读依赖项属性:

代码语言:javascript
复制
<bindings:BindingHub 
       Visibility="Hidden"
       Socket1="{Binding ActualWidth, ElementName=Item, Mode=OneWay}"
       Socket2="{Binding ItemWidth, Mode=OneWayToSource}"
       Connect="(1 in, 2 out)"/>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5061237

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档