Привязать к ActualHeight Item ItemsControl - PullRequest
5 голосов
/ 21 февраля 2011

У меня есть два отдельных ItemsControl, которые появляются рядом.ItemsControl s связываются с одним и тем же ItemsSource, но они отображают данные по-разному.

Каждый элемент, отображаемый слева, скорее всего будет меньше, чем тот же элемент справа.Это вызывает проблему, поскольку строки не будут выстроены в ряд, поэтому мне нужно, чтобы элемент слева связывался с элементом справа.

ItemsControl        ItemsControl
|Item 1         |Item 1
|Item 2         |Item 2
|Item 3         |
|Item 4         |Item 3

Как видите, элемент 2 справа большетак что скинуть выравнивание.Так что, если я смогу связать левый пункт 2 с правым пунктом 2 ActualHeight, проблема будет решена.Как я могу сделать это в XAML?

Редактировать: Чтобы усложнить задачу, ItemsControl справа необходимо прокрутить справа налево, но оба ItemsControls необходимо прокрутитьвверх и вниз вместе.По сути, левый обеспечивает своего рода заголовок для элементов справа.

Ответы [ 3 ]

3 голосов
/ 22 февраля 2011

В ответ на Jobi Joy's ответ

Невозможно выполнить прямую привязку OneWayToSource в Xaml для свойства ActOnight для зависимости ReadOnly, но есть много обходных путей. Ответ Кент Бугаарт в этот вопрос мой любимый. Что он делает, так это то, что использует присоединенное поведение, которое прослушивает событие SizeChanged любого FrameworkElement и обновляет два вложенных свойства: ширину и высоту соответственно.

Например, TextBlock, ActualHeight может использоваться для вставки в свойство Height модели представления, например

.
<TextBlock local:ActualSizeBehavior.ObserveActualSize="True"
           local:ActualSizeBehavior.ActualHeight="{Binding Path=Height,
                                                           Mode=OneWayToSource}"
           .../>

Синхронизировать два ScrollViewers
Вы можете использовать DependencyPropertyDescriptor для прослушивания изменений в свойстве VerticalOffsetProperty или подписаться на событие ScrollChanged и вызвать ScrollToVerticalOffset. Пример * * тысяча двадцать семь

Xaml

<ScrollViewer Name="scrollViewerLeft"
              ScrollChanged="scrollViewerLeft_ScrollChanged">
<ScrollViewer Name="scrollViewerRight"
              ScrollChanged="scrollViewerRight_ScrollChanged">

Код за обработчиками событий

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

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);
    }
}
0 голосов
/ 23 декабря 2014

Взгляните на мою статью: http://www.codeproject.com/KB/WPF/BindingHub.aspx

Вот как вы можете привязать свойства зависимости только для чтения с помощью BindingHub:

<bindings:BindingHub 
       Visibility="Hidden"
       Socket1="{Binding ActualWidth, ElementName=Item, Mode=OneWay}"
       Socket2="{Binding ItemWidth, Mode=OneWayToSource}"
       Connect="(1 in, 2 out)"/>
0 голосов
/ 21 февраля 2011

Поскольку ItemsSource одинаково для обоих, вы можете использовать одну ItemsControl и целую строку, представленную в виде двух секций (двух столбцов сетки) внутри этой единственной DataTemplate, тогда высоты будут выровнены автоматически.Вы всегда можете оформить его так, чтобы он выглядел так, как будто он является частью двух разных ItemsControl, но технически единых.

Еще один способ сделать это - добавить свойство Height в ViewModel (, конечно, нет.очень правильный дизайн, так как добавление View view к VM ).TwoWay привязывает высоту к ActualHeight элемента left-itemsControl ItemContainerStyle.А в элементе управления right-items свяжите это свойство Height с высотой ItemsContainerStyle {One Way}.Таким образом, оба будут синхронизированы.

Еще одна идея, основанная на вашем обновлении «Необходимость прокрутки с правой стороны»: используйте один ListView и включите в него два столбца, и из этих двух GridViewColumn.CellTemplate будут ваши два DataTemplates.Эта идея все еще нуждается в замораживании столбцов в первом столбце.Но это может быть сложнее.

В любом случае, я бы пошел с первым подходом здесь.

...