2

ListBox の垂直スクロール バーが折りたたまれている場合に、別の ListBox の上に配置される Border または Margin の幅または可視性を調整したいと考えています。

私はこのようなことを試みていますが、ListBox ScrollViewer にアクセスする方法がわかりません。明らかに、DataTrigger のパスは正しくありません。

<Border Width={Binding Source={x:Static SystemParameters.ScrollWidth}}">
   <Border.Style>
      <Style>
         <Setter Property="Border.Visibility" Value="Visible"/>
         <Style.Triggers>
            <DataTrigger Binding="{Binding ElementName=listBox, 
                         Path=***ScrollViewer.ComputedVerticalScrollBarVisibility***}"
                         Value="Collapsed">
               <Setter Property="Border.Visibility" Value="Collapsed"/>
            </DataTrigger>
         </Style.Triggers>
      </Style>
   </Border.Style>
</Border>

<ListBox Name="listBox" ItemsSource="{Binding MyItems}"/>

その ListBox プロパティにアクセスする方法はありますか? そうでない場合、この問題を解決するためのより良い方法はありますか?

どうもありがとう!

4

1 に答える 1

3

ListBox を別の ScrollViewer にラップする回避策により、冗長な ScrollViewer コントロールを犠牲にして、すべての XAML ソリューションが可能になります (質問のコメントを参照)。最終的に、私のチームメイトは、次のコード ビハインド ソリューションを採用することにしました。

アクセスする必要がある ScrollViewer を持つ ListBox の関連属性を次に示します。

<ListBox Name="_listBox" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
         Loaded="InitializeListBoxScrollViewerProperty"/>

外部コントロールで使用するスクロール ビューアを公開するコード ビハインドを次に示します。

private static readonly DependencyPropertyKey ListBoxScrollViewerPropertyKey =
   DependencyProperty.RegisterReadOnly("ListBoxScrollViewer", typeof(ScrollViewer),
   typeof(MyEditView), new PropertyMetadata());

protected static readonly DependencyProperty ListBoxScrollViewerProperty =
   ListBoxScrollViewerPropertyKey.DependencyProperty;

protected ScrollViewer ListBoxScrollViewer
{
   get { return (ScrollViewer)GetValue(ListBoxScrollViewerProperty); }
   private set { SetValue(ListBoxScrollViewerPropertyKey, value); }
}

private void InitializeListBoxScrollViewerProperty(object sender, RoutedEventArgs args)
{
   if (ReferenceEquals(args.OriginalSource, _listBox))
   {
      var scrollViewer = _listBox.GetFirstDescendantBreadthFirst<ScrollViewer>();
      if (scrollViewer != null)
      {
         ListBoxScrollViewer = scrollViewer;
      }
   }
}

使用される拡張メソッドは次のとおりです。

public static class DependencyObjectExtensions
{
   public static TDescendant GetFirstDescendantBreadthFirst<TDescendant>
      (this DependencyObject dependencyObject) where TDescendant : DependencyObject
   {
      if (dependencyObject == null) { throw new ArgumentNullException(); }
      return GetFirstDescendantBreadthFirst<TDescendant>(GetAllChildren(dependencyObject));
   }

   private static TDescendant GetFirstDescendantBreadthFirst<TDescendant>
      (IEnumerable<DependencyObject> descendants) where TDescendant : DependencyObject
   {
      if (!descendants.Any()) return null;
      var descendant = descendants.OfType<TDescendant>().FirstOrDefault();
      if (descendant != null) return descendant;
      return GetFirstDescendantBreadthFirst<TDescendant>(descendants.SelectMany(GetAllChildren));
   }

   private static IEnumerable<DependencyObject> GetAllChildren(DependencyObject dependencyObject)
   {
      return Enumerable
         .Range(0, VisualTreeHelper.GetChildrenCount(dependencyObject))
         .Select(i => VisualTreeHelper.GetChild(dependencyObject, i));
   }
}

最後に、XAML の別の部分でスクロール ビューアーにアクセスできます。

<Grid>
   <Grid.Style>
      <Style TargetType="Grid">
         <Style.Triggers>
            <DataTrigger Binding="{Binding ListBoxScrollViewer.ComputedVerticalScrollBarVisibility,
               RelativeSource={RelativeSource AncestorType=l:MyEditView}}" Value="Visible">
               <Setter Property="Margin" Value="{StaticResource myWidenedMargin}"/>
            </DataTrigger>
         </Style.Triggers>
      </Style>
   </Grid.Style>
</Grid>
于 2012-12-14T15:07:56.647 に答える